From b7a37a1899772e16ce5550c6be3ff9cfd9825fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 27 Feb 2025 08:20:21 +0000 Subject: Add inital empty files for GDT --- .../include/arch/context_switching/descriptor_table/access_bytes.hpp | 0 arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp | 0 .../arch/context_switching/descriptor_table/global_descriptor_table.hpp | 0 .../arch/context_switching/descriptor_table/segment_descriptor.hpp | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/access_bytes.hpp create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_bytes.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_bytes.hpp new file mode 100644 index 0000000..e69de29 diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp new file mode 100644 index 0000000..e69de29 diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp new file mode 100644 index 0000000..e69de29 diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3 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 --- .../descriptor_table/gdt_flags.hpp | 68 ++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp index e69de29..83a7c06 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp @@ -0,0 +1,68 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP + +#include +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + /** + * @brief Defines helper function for all states that the global descriptor flags of a segment descriptor can + * have. + * + * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. + */ + struct gdt_flags + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + GRANULARITY = 1U << 0U, ///< Indicates the size the Limit value in the segement descriptor is scaled by 1 Byte + ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. + PROTECTED_MODE_SEGMENT_16_OR_32_BIT_SIZE = 1U << 1U, ///< Descriptor defines either a 16-bit protected mdoe + ///< segment if bit is not set or 32-bit if the bit is set. + ENABLE_LONG_MODE = 1U << 2U ///< If set the descriptor defines a 64-bit code segment, when set + ///< PROTECTED_MODE_SEGMENT_16_OR_32_BIT_SIZE should always be clear. For other types + ///< of segments bit should not be set. + }; + + /** + * @brief Constructor. + * + * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to + * allow reading the state of single bits more easily. Only the first 3 bit of the value will actually be converted + * into the std::bitset, because the latter 4 bits are not relevant and the 4th bit is reserved. + */ + explicit gdt_flags(uint8_t flags) + : flags(flags >> 5U) + { + // Nothing to do + } + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + */ + auto contains_flags(std::bitset<4U> other) const -> bool; + + /** + * @brief Allows to compare the underlying std::bitset of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying std::bitset of both types is the same. + */ + auto operator==(gdt_flags const & other) const -> bool = default; + + private: + std::bitset<4U> flags; ///< Underlying bitset used to read the flags from. + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP -- 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 --- .../descriptor_table/access_byte.hpp | 87 ++++++++++++++++++++++ .../descriptor_table/access_bytes.hpp | 0 2 files changed, 87 insertions(+) create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/access_bytes.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp new file mode 100644 index 0000000..b3bce11 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp @@ -0,0 +1,87 @@ + +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_POINTERS_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_POINTERS_HPP + +#include +#include +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + enum class privilege_level + { + KERNEL = 0, + ADMIN = 1, + PRIVILEGED_USER = 2, + USER = 3 + }; + + /// @brief Defines the access byte of a Descriptor Table + struct access_byte + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + PRESENT = 1U << 0U, ///< Present bit; Allows an entry to refer to a valid segment. + ///< Must be set (1) for any valid segment. + PRIVILEGE_LEVEL = 1U << 1U | 1 << 2U, ///< Descriptor privilege level field. + ///< Contains the CPU Privilege level of the segment. + DESCRIPTOR_TYPE = 1U << 3U, ///< Defines a system segment (if 0) or a code/data segment (if 1). + EXECUTABLE = 1U << 4U, ///< Defines a data segment (if 0) or a code segment which can be executed from (if 1). + CONFORMING = 1U << 5U, ///< For data selectors: Direction bit + ///< Grows up (if 0), grows down (if 1) + ///< For code selectors: Conforming bit + ///< Code can only be executed from the DPL ring (if 0) + ///< Code can be executed from equal or lower DPL ring (if 1) + READ_WRITE = 1U << 6U, ///< For code segments: Readable bit + ///< For data segments: Writeable bit (read is always allowed) + ACCESSED = 1U << 7U ///< Set, when the segment is accessed. If GDT descriptor is stored in read only pages and + ///< this bit is set to 0, the CPU trying to set this bit will trigger a page fault. + }; + + /** + * @brief Constructor. + * + * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to + * allow reading the state of single bits more easily. + */ + explicit access_byte(uint8_t flags) + : flags(flags) + { + // Nothing to do + } + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + */ + auto contains_flags(std::bitset<8U> other) const -> bool; + + /** + * @brief Returns the privilege level of the current access_byte + * + * @return privilege_level + */ + auto get_privilege_level() const -> privilege_level; + + /** + * @brief Allows to compare the underlying std::bitset of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying std::bitset of both types is the same. + */ + auto operator==(access_byte const & other) const -> bool = default; + + private: + std::bitset<8U> flags; ///< Underlying bitset used to read the flags from + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_POINTERS_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_bytes.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_bytes.hpp deleted file mode 100644 index e69de29..0000000 -- cgit v1.2.3 From 2f7db60472629dbd191c00e6010d120a046f5ab9 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Feb 2025 13:09:55 +0000 Subject: start segment_descriptor --- .../descriptor_table/access_byte.hpp | 6 ++-- .../descriptor_table/segment_descriptor.hpp | 41 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp index b3bce11..36b22ce 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp @@ -1,6 +1,6 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_POINTERS_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_POINTERS_HPP +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP #include #include @@ -84,4 +84,4 @@ namespace teachos::arch::context_switching::descriptor_table }; } // namespace teachos::arch::context_switching::descriptor_table -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_POINTERS_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index e69de29..ced0d89 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -0,0 +1,41 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP + +#include "arch/context_switching/descriptor_table/gdt_flags.hpp" + +#include +#include +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + struct segment_descriptor + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint64_t + { + BASE = 1U << 0U, + FLAGS = 1U << 8U, + LIMIT = 1U << 12U, + ACCESS_BYTE = 1U << 16U, + BASE = 1U << 32U, + BASE = 1U << 40U, + LIMIT = 1U << 56U + }; + + explicit segment_descriptor(uint64_t flags) + : flags(flags) + { + // Nothing to do + } + + private: + std::uint8_t base1; + gdt_flags flags; + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP \ No newline at end of file -- cgit v1.2.3 From 56ee767e37cdccae333b292f2fd4c7b2123a7108 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Feb 2025 13:12:06 +0000 Subject: add comment --- .../arch/context_switching/descriptor_table/segment_descriptor.hpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index ced0d89..8428dfa 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -9,6 +9,11 @@ namespace teachos::arch::context_switching::descriptor_table { + + /* + TODO: Lookup segment_descriptor in intel manual chapter 3.4.5 + */ + struct segment_descriptor { /** -- cgit v1.2.3 From 051307f49f4cdfb86c527a475ab21feea4a664d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 4 Mar 2025 18:01:49 +0000 Subject: Add more methods to vector to mimic stl interface partially. --- arch/x86_64/include/arch/stl/shared_pointer.hpp | 2 + arch/x86_64/include/arch/stl/vector.hpp | 381 ++++++++++++++++++------ 2 files changed, 297 insertions(+), 86 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/stl/shared_pointer.hpp b/arch/x86_64/include/arch/stl/shared_pointer.hpp index 79a9f82..4a9dec5 100644 --- a/arch/x86_64/include/arch/stl/shared_pointer.hpp +++ b/arch/x86_64/include/arch/stl/shared_pointer.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP #define TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP +#include + namespace teachos::arch::stl { template diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index 62be704..5bebf62 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -2,190 +2,399 @@ #define TEACHOS_ARCH_X86_64_STL_VECTOR_HPP #include "arch/exception_handling/panic.hpp" -#include "arch/shared/container.hpp" -#include "arch/shared/contiguous_pointer_iterator.hpp" #include +#include namespace teachos::arch::stl { /** * @brief Custom vector implementation mirroring the std::vector to allow for the usage of STL functionality with our - * custom memory management + * custom memory management. * - * @tparam T Element the vector instance should contain + * @tparam T Element the vector instance should contain. */ template struct vector { /** - * @brief Defaulted constructor. Initalizes empty vector + * @brief Defaulted constructor. Initalizes empty vector. */ vector() = default; /** * @brief Constructs data with the given amount of elements containg the given value or alterantively the default - * constructed value + * constructed value. * - * @param capacity Amount of elements we want to create and set the given value for - * @param initial Inital value of all elements in the underlying data array + * @param capacity Amount of elements we want to create and set the given value for. + * @param initial Inital value of all elements in the underlying data array. */ - vector(size_t capacity, T initial = T{}) - : capacity(capacity) - , size(capacity) - , data(new T[capacity]{}) + explicit vector(size_t capacity, T initial = T{}) + : _size(capacity) + , _capacity(capacity) + , _data(new T[_capacity]{}) { - auto const begin = data; - auto const end = data + size; - vector_container container{begin, end}; - std::ranges::fill(container, inital); + std::ranges::fill(begin(), end(), initial); } /** - * @brief Copy constructor + * @brief Constructs data by copying all element from the given exclusive range. + * + * @tparam InputIterator Template that should have atleast input iterator characteristics. + * @param first Input iterator to the first element in the range we want to copy from. + * @param last Input iterator to one past the last element in the range we want to copy from. + */ + template + explicit vector(InputIterator first, InputIterator last) + : _size(std::distance(first, last)) + , _capacity(std::distance(first, last)) + , _data(new T[_capacity]{}) + { + std::copy(first, last, _data); + } + + /** + * @brief Construct data by copying all elements from the initializer list. + * + * @param initalizer_list List we want to copy all elements from. + */ + explicit vector(std::initializer_list initalizer_list) + : _size(initalizer_list.size()) + , _capacity(initalizer_list.size()) + , _data(new T[_capacity]{}) + { + std::copy(initalizer_list.begin(), initalizer_list.end(), _data); + } + + /** + * @brief Copy constructor. * * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all - * elements from it + * elements from it. * - * @param other Other instance of vector we want to copy the data from + * @param other Other instance of vector we want to copy the data from. */ vector(vector const & other) - : size(size) - , capacity(capacity) + : _size(other._size) + , _capacity(other._capacity) { - delete[] data; - data = new T[capacity]{}; - - auto const begin = other.data; - auto const end = other.data + size; - vector_container container{begin, end}; - std::ranges::copy(container, data); + delete[] _data; + _data = new T[_capacity]{}; + std::copy(other.begin(), other.end(), _data); } /** - * @brief Copy assignment operator + * @brief Copy assignment operator. * * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all - * elements from it + * elements from it. * - * @param other Other instance of vector we want to copy the data from - * @return Newly created copy + * @param other Other instance of vector we want to copy the data from. + * @return Newly created copy. */ vector & operator=(vector const & other) { - delete[] data; - size = other.size(); - capacity = other.capacity(); - data = new T[capacity]{}; - - auto const begin = other.data; - auto const end = other.data + size; - vector_container container{begin, end}; - std::ranges::copy(container, data); + delete[] _data; + _size = other._size; + _capacity = other._capacity; + _data = new T[_capacity]{}; + std::copy(other.begin(), other.end(), _data); return *this; } /** - * @brief Destructor + * @brief Destructor. */ - ~vector() { delete[] data; } + ~vector() { delete[] _data; } /** * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If - * that is the case the capacity is increased automatically + * that is the case the capacity is increased automatically. * - * @return Current amount of elements + * @return Current amount of elements. */ - size_t size() const { return size; } + size_t size() const { return _size; } /** * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we - * exactly require to decrease the amount of allocations and deallocation to improve speed + * exactly require to decrease the amount of allocations and deallocation to improve speed. * - * @return Current amount of space the vector has for elements + * @return Current amount of space the vector has for elements. */ - size_t capacity() const { return capacity; } + size_t capacity() const { return _capacity; } /** - * @brief Array indexing operator. Allowing to access element at the given index + * @brief Array indexing operator. Allowing to access element at the given index. * - * @note Does not do any bounds checks use at() for that + * @note Does not do any bounds checks use at() for that. * - * @param index Index we want to access elements at - * @return Reference to the underlying element + * @param index Index we want to access elements at. + * @return Reference to the underlying element. */ - T & operator[](size_t index) { return data[index]; } + T & operator[](size_t index) { return _data[index]; } /** - * @brief Array indexing operator. Allowing to access element at the given index + * @brief Array indexing operator. Allowing to access element at the given index. * - * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted + * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. * - * @param index Index we want to access elements at - * @return Reference to the underlying element + * @param index Index we want to access elements at. + * @return Reference to the underlying element. */ T & at(size_t index) { - if (index >= size) + if (index >= _size) { exception_handling::panic("[Vector] Attempted to read element at invalid index"); } - return this->operator[](size); + return this->operator[](index); } - void push_back(T & const element) {} + /** + * @brief Appends the given element value to the end of the container. The new element is initalized as a copy of + * value. + * + * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, + * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. + * Otherwise only the end() iterator is invalidated. + * + * @param value The value of the element to append. + */ + void push_back(T const & value) + { + _data[_size] = value; + _size++; - void emplace_back(T && const element) + if (_size == _capacity) + { + reserve(_capacity * 2); + } + } + + /** + * @brief Appends the given element value to the end of the container. Value is moved into the new element. + * + * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, + * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. + * Otherwise only the end() iterator is invalidated. + * + * @param value The value of the element to append. + */ + void push_back(T && value) { - // If no cacacity, increase capacity - if (size == capacity) + _data[_size] = std::move(value); + _size++; + + if (_size == _capacity) { - reserve(capacity * 2); + reserve(_capacity * 2); } + } - data[size] = element; - size++; + /** + * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the + * template type. The arguments args... are forwarded to the constructor as std::forward(args).... + * + * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case + * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only + * the end() iterator is invalidated. + * + * @tparam Args + * @param args Arguments to forward to the constructor of the element + * @return T& + */ + template + auto emplace_back(Args &&... args) -> T & + { + _data[_size] = T{std::forward(args)...}; + auto const index = _size++; + + if (_size == _capacity) + { + reserve(_capacity * 2); + } + return _data[index]; } + /** + * @brief Removes the last element of the container. Calling pop_back on an empty container results in halting the + * further execution. Iterators and references to the last element are invalidated. The end() + * iterator is also invalidated. + */ void pop_back() { - if (size <= 0) + if (_size <= 0) { exception_handling::panic("[Vector] Attempted to pop back last element of already empty vector"); } - size--; + _size--; } - T & front() { return *data; } + /** + * @brief Returns an iterator to the first element of the vector. + * If the vector is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + T * begin() noexcept { return _data; } + + /** + * @brief Returns an iterator to the first element of the vector. + * If the vector is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + T const * begin() const noexcept { return _data; } + + /** + * @brief Returns an iterator to the first element of the vector. + * If the vector is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + T const * cbegin() const noexcept { return begin(); } + + /** + * @brief Returns an iterator to the element following the last element of the vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + T * end() noexcept { return _data + _size; } + + /** + * @brief Returns an iterator to the element following the last element of the vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + T const * end() const noexcept { return _data + _size; } + + /** + * @brief Returns an iterator to the element following the last element of the vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + T const * cend() const noexcept { return end(); } + + /** + * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range + * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable + * in that case). + * + * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal + * to the address of the first element. + */ + T * data() { return _data; } + + /** + * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range + * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable + * in that case). + * + * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal + * to the address of the first element. + */ + T const * data() const { return _data; } - T & back() { return *(data + size); } + /** + * @brief Returns a reference to the first element in the container. Calling front on an empty container causes + * undefined behavior. + * + * @return Reference to the first element. + */ + T & front() { return *begin(); } + + /** + * @brief Returns a reference to the first element in the container. Calling front on an empty container causes + * undefined behavior. + * + * @return Reference to the first element. + */ + T const & front() const { return *begin(); } + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + T & back() { return *end(); } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + T const & back() const { return *end(); } + + /** + * @brief Increase the capacity of the vector (the total number of elements that the vector can hold without + * requiring reallocation) to a value that's greater or equal to new_cap. If new_cap is greater than the current + * capacity(), new storage is allocated, otherwise the function does nothing. + * + * reserve() does not change the size of the vector. + * + * If new_cap is greater than capacity(), all iterators (including the end() iterator) and all references to the + * elements are invalidated. Otherwise, no iterators or references are invalidated. + * + * After a call to reserve(), insertions will not trigger reallocation unless the insertion would make the size of + * the vector greater than the value of capacity(). + * + * @note Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for + * instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing + * the capacity to grow linearly rather than exponentially) and result in increased computational complexity and + * decreased performance. For example, a function that receives an arbitrary vector by reference and appends + * elements to it should usually not call reserve() on the vector, since it does not know of the vector's usage + * characteristics. + * + * When inserting a range, the range version of insert() is generally preferable as it preserves the correct + * capacity growth behavior, unlike reserve() followed by a series of push_back()s. + * + * reserve() cannot be used to reduce the capacity of the container; to that end shrink_to_fit() is provided. + * + * @param new_capacity New capacity of the vector, in number of elements + */ void reserve(size_t new_capacity) { - if (new_capacity < size) + if (new_capacity <= _capacity) { - // Creating new array with less capacity than is required to keep all current elements makes no sense return; } - T * temp = new T[new_capacity]; + _capacity = new_capacity; + T * temp = new T[_capacity]{}; + std::copy(begin(), end(), temp); + delete[] _data; + _data = temp; + } - auto const begin = other.data; - auto const end = other.data + capacity; - vector_container container{begin, end}; - std::ranges::copy(container, temp); + /** + * @brief Requests the removal of unused capacity. Meaning it requests to reduce capacity() to size(). + * + * If reallocation occurs, all iterators (including the end() iterator) and all references to the elements are + * invalidated. If no reallocation occurs, no iterators or references are invalidated. + */ + void shrink_to_fit() + { + if (_size == _capacity) + { + return; + } - delete[] data; - capacity = new_capacity; - data = temp; + _capacity = _size; + T * temp = new T[_capacity]{}; + std::copy(begin(), end(), temp); + delete[] _data; + _data = temp; } private: - T * data = {}; ///< Pointer to the first element in the underlying data container - size_t capacity = {}; ///< Amount of space for elements in the underlying data container - size_t size = {}; ///< Amount of elements in the underlying data container - - typedef shared::container> vector_container; + size_t _size = {}; ///< Amount of elements in the underlying data container + size_t _capacity = {}; ///< Amount of space for elements in the underlying data container + T * _data = {}; ///< Pointer to the first element in the underlying data container }; } // namespace teachos::arch::stl -- cgit v1.2.3 From 06d5e5872838bd1528493b62b4dc28d44b54aa47 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 9 Mar 2025 09:30:01 +0000 Subject: add doxygen comments to shared and unique pointer --- arch/x86_64/include/arch/stl/shared_pointer.hpp | 93 ++++++++++++++++++++++++- arch/x86_64/include/arch/stl/unique_pointer.hpp | 71 ++++++++++++++++++- 2 files changed, 161 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/stl/shared_pointer.hpp b/arch/x86_64/include/arch/stl/shared_pointer.hpp index 4a9dec5..80ca7fe 100644 --- a/arch/x86_64/include/arch/stl/shared_pointer.hpp +++ b/arch/x86_64/include/arch/stl/shared_pointer.hpp @@ -5,15 +5,33 @@ namespace teachos::arch::stl { + /** + * @brief A simple implementation of a shared pointer. + * + * This class provides reference counting and automatic resource management + * for dynamically allocated objects. + * + * @tparam T The type of the managed object. + */ template struct shared_pointer { + /** + * @brief Constructs a shared pointer. + * + * @param pointer Raw pointer to manage (default is nullptr). + */ explicit shared_pointer(T * pointer = nullptr) : pointer(pointer) , ref_count(new std::atomic(pointer != nullptr ? 1 : 0)) { } + /** + * @brief Copy constructor. + * + * @param other The shared_pointer to copy from. + */ shared_pointer(const shared_pointer & other) : pointer(other.pointer) , ref_count(other.ref_count) @@ -24,6 +42,11 @@ namespace teachos::arch::stl } } + /** + * @brief Move constructor. + * + * @param other The shared_pointer to move from. + */ shared_pointer(shared_pointer && other) noexcept : pointer(other.pointer) , ref_count(other.ref_count) @@ -32,6 +55,12 @@ namespace teachos::arch::stl other.ref_count = nullptr; } + /** + * @brief Copy assignment operator. + * + * @param other The shared_pointer to copy from. + * @return Reference to this shared_pointer. + */ shared_pointer & operator=(const shared_pointer & other) { if (this != &other) @@ -49,6 +78,12 @@ namespace teachos::arch::stl return *this; } + /** + * @brief Move assignment operator. + * + * @param other The shared_pointer to move from. + * @return Reference to this shared_pointer. + */ shared_pointer & operator=(shared_pointer && other) noexcept { if (this != &other) @@ -63,8 +98,14 @@ namespace teachos::arch::stl return *this; } + /** + * @brief Destructor. Cleans up resources if necessary. + */ ~shared_pointer() { cleanup(); } + /** + * @brief Releases ownership and deletes the object if necessary. + */ void cleanup() { if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0) @@ -74,6 +115,11 @@ namespace teachos::arch::stl } } + /** + * @brief Resets the shared pointer with a new raw pointer. + * + * @param p New raw pointer (default is nullptr). + */ void reset(T * p = nullptr) { cleanup(); @@ -81,18 +127,43 @@ namespace teachos::arch::stl ref_count = new std::atomic(p != nullptr ? 1 : 0); } + /** + * @brief Swaps the contents of this shared pointer with another. + * + * @param other The shared_pointer to swap with. + */ void swap(shared_pointer & other) { std::swap(pointer, other.pointer); std::swap(ref_count, other.ref_count); } + /** + * @brief Dereference operator. + * + * @return Reference to the managed object. + */ T & operator*() const { return *pointer; } + /** + * @brief Member access operator. + * + * @return Pointer to the managed object. + */ T * operator->() const { return pointer; } + /** + * @brief Returns the raw pointer. + * + * @return Pointer to the managed object. + */ T * get() const { return pointer; } + /** + * @brief Returns the reference count. + * + * @return Number of shared_pointer instances managing the same object. + */ int use_count() const { if (pointer != nullptr) @@ -103,15 +174,33 @@ namespace teachos::arch::stl return 0; } + /** + * @brief Checks if this is the only shared pointer managing the object. + * + * @return True if the use count is 1, otherwise false. + */ bool unique() const { return use_count() == 1; } + /** + * @brief Checks if the shared pointer is not empty. + * + * @return True if the pointer is not null, otherwise false. + */ explicit operator bool() const { return pointer != nullptr; } private: - T * pointer; - std::atomic * ref_count; + T * pointer; ///< The managed object. + std::atomic * ref_count; ///< Reference count. }; + /** + * @brief Creates a shared pointer instance. + * + * @tparam T The type of object to allocate. + * @tparam Args Argument types for the constructor of T. + * @param args Arguments for the constructor of T. + * @return A shared_pointer instance managing a newly created object. + */ template shared_pointer make_shared(Args &&... args) { diff --git a/arch/x86_64/include/arch/stl/unique_pointer.hpp b/arch/x86_64/include/arch/stl/unique_pointer.hpp index 0ec3c38..08c862d 100644 --- a/arch/x86_64/include/arch/stl/unique_pointer.hpp +++ b/arch/x86_64/include/arch/stl/unique_pointer.hpp @@ -3,25 +3,56 @@ namespace teachos::arch::stl { + /** + * @brief A simple unique pointer implementation. + * + * @tparam T Type of the managed object. + */ template struct unique_pointer { + /** + * @brief Constructs a unique pointer. + * + * @param ptr Pointer to manage, default is nullptr. + */ explicit unique_pointer(T * ptr = nullptr) : pointer(ptr) { } + /** + * @brief Destructor that deletes the managed object. + */ ~unique_pointer() { delete pointer; } + /** + * @brief Deleted copy constructor to enforce unique ownership. + */ unique_pointer(const unique_pointer &) = delete; + + /** + * @brief Deleted copy assignment operator to enforce unique ownership. + */ unique_pointer & operator=(const unique_pointer &) = delete; + /** + * @brief Move constructor. + * + * @param other Unique pointer to move from. + */ unique_pointer(unique_pointer && other) noexcept : pointer(other.pointer) { other.pointer = nullptr; } + /** + * @brief Move assignment operator. + * + * @param other Unique pointer to move from. + * @return Reference to this unique pointer. + */ unique_pointer & operator=(unique_pointer && other) noexcept { if (this != &other) @@ -33,12 +64,32 @@ namespace teachos::arch::stl return *this; } + /** + * @brief Dereference operator. + * + * @return Reference to the managed object. + */ T & operator*() const { return *pointer; } + /** + * @brief Member access operator. + * + * @return Pointer to the managed object. + */ T * operator->() const { return pointer; } + /** + * @brief Gets the raw pointer. + * + * @return The managed pointer. + */ T * get() const { return pointer; } + /** + * @brief Releases ownership of the managed object. + * + * @return The raw pointer and sets internal pointer to nullptr. + */ T * release() { T * temp = pointer; @@ -46,18 +97,36 @@ namespace teachos::arch::stl return temp; } + /** + * @brief Resets the managed object. + * + * @param ptr New pointer to manage (default is nullptr). + */ void reset(T * ptr = nullptr) { delete pointer; pointer = ptr; } + /** + * @brief Swaps the managed object with another unique pointer. + * + * @param other Unique pointer to swap with. + */ void swap(unique_pointer & other) { std::swap(pointer, other.pointer); } private: - T * pointer; + T * pointer; ///< The managed pointer. }; + /** + * @brief Creates a unique pointer instance. + * + * @tparam T Type of the managed object. + * @tparam Args Argument types for T's constructor. + * @param args Arguments for T's constructor. + * @return A unique pointer managing a newly created T object. + */ template unique_pointer make_unique(Args &&... args) { -- cgit v1.2.3 From 1a6d41362447531a2ea5ee344c15b9aaa6c2090a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 9 Mar 2025 16:52:17 +0000 Subject: Adjust comments and implement remaining interface for STL classes. --- arch/x86_64/include/arch/stl/shared_pointer.hpp | 142 ++++++++++++++---------- arch/x86_64/include/arch/stl/unique_pointer.hpp | 96 +++++++++++----- arch/x86_64/include/arch/stl/vector.hpp | 18 +-- 3 files changed, 162 insertions(+), 94 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/stl/shared_pointer.hpp b/arch/x86_64/include/arch/stl/shared_pointer.hpp index 80ca7fe..1ddc182 100644 --- a/arch/x86_64/include/arch/stl/shared_pointer.hpp +++ b/arch/x86_64/include/arch/stl/shared_pointer.hpp @@ -6,10 +6,14 @@ namespace teachos::arch::stl { /** - * @brief A simple implementation of a shared pointer. - * - * This class provides reference counting and automatic resource management - * for dynamically allocated objects. + * @brief Shared_pointer is a smart pointer that retains shared ownership of an object through a pointer. Several + * shared_pointer objects may own the same object. The object is destroyed and its memory deallocated when either of + * the following happens: the last remaining shared_pointer owning the object is destroyed; the last remaining + * shared_pointer owning the object is assigned another pointer via operator= or reset(). A + * shared_pointer can share ownership of an object while storing a pointer to another object. This feature can be used + * to point to member objects while owning the object they belong to. The stored pointer is the one accessed by get(), + * the dereference and the comparison operators. The managed pointer is the one passed to the deleter when use count + * reaches zero. * * @tparam T The type of the managed object. */ @@ -17,14 +21,15 @@ namespace teachos::arch::stl struct shared_pointer { /** - * @brief Constructs a shared pointer. + * @brief Constructor. * - * @param pointer Raw pointer to manage (default is nullptr). + * @param pointer A pointer to an object to manage (default is nullptr). */ explicit shared_pointer(T * pointer = nullptr) : pointer(pointer) - , ref_count(new std::atomic(pointer != nullptr ? 1 : 0)) + , ref_count(new std::atomic(pointer != nullptr ? 1 : 0)) { + // Nothing to do. } /** @@ -56,10 +61,12 @@ namespace teachos::arch::stl } /** - * @brief Copy assignment operator. + * @brief Copy assignment operator. Replaces the managed object with the one managed by r. Shares ownership of the + * object managed by r. If r manages no object, *this manages no object too. Equivalent to + * shared_ptr(r).swap(*this). * - * @param other The shared_pointer to copy from. - * @return Reference to this shared_pointer. + * @param other Another smart pointer to share the ownership with. + * @return Reference to this shared pointer. */ shared_pointer & operator=(const shared_pointer & other) { @@ -79,10 +86,11 @@ namespace teachos::arch::stl } /** - * @brief Move assignment operator. + * @brief Move assignment operator. Move-assigns a shared_ptr from r. After the assignment, *this contains a copy of + * the previous state of r, and r is empty. Equivalent to shared_ptr(std::move(r)).swap(*this). * - * @param other The shared_pointer to move from. - * @return Reference to this shared_pointer. + * @param other Another smart pointer to acquire the ownership from. + * @return Reference to this shared pointer. */ shared_pointer & operator=(shared_pointer && other) noexcept { @@ -104,31 +112,20 @@ namespace teachos::arch::stl ~shared_pointer() { cleanup(); } /** - * @brief Releases ownership and deletes the object if necessary. - */ - void cleanup() - { - if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0) - { - delete pointer; - delete ref_count; - } - } - - /** - * @brief Resets the shared pointer with a new raw pointer. + * @brief Replaces the managed object. * - * @param p New raw pointer (default is nullptr). + * @param ptr Pointer to a new object to manage (default = nullptr). */ - void reset(T * p = nullptr) + void reset(T * ptr = nullptr) { cleanup(); - pointer = p; - ref_count = new std::atomic(p != nullptr ? 1 : 0); + pointer = ptr; + ref_count = new std::atomic(ptr != nullptr ? 1 : 0); } /** - * @brief Swaps the contents of this shared pointer with another. + * @brief Exchanges the stored pointer values and the ownerships of *this and r. Reference counts, if any, are not + * adjusted. * * @param other The shared_pointer to swap with. */ @@ -139,32 +136,38 @@ namespace teachos::arch::stl } /** - * @brief Dereference operator. + * @brief Dereference operator. If get() is a null pointer, the behavior is undefined. * - * @return Reference to the managed object. + * @return Returns the object owned by *this, equivalent to *get(). */ - T & operator*() const { return *pointer; } + auto operator*() const -> T & { return *pointer; } /** * @brief Member access operator. * - * @return Pointer to the managed object. + * @return Returns a pointer to the object owned by *this, i.e. get(). */ - T * operator->() const { return pointer; } + auto operator->() const -> T * { return pointer; } /** - * @brief Returns the raw pointer. + * @brief Returns a pointer to the managed object or nullptr if no object is owned. * - * @return Pointer to the managed object. + * @return Pointer to the managed object or nullptr if no object is owned. */ - T * get() const { return pointer; } + auto get() const -> T * { return pointer; } /** - * @brief Returns the reference count. + * @brief Returns the number of different shared_pointer instances (*this included) managing the current object. If + * there is no managed object, ​0​ is returned. * - * @return Number of shared_pointer instances managing the same object. + * @note Common use cases include comparison with ​0​. If use_count returns zero, the shared pointer is empty + * and manages no objects (whether or not its stored pointer is nullptr). Comparison with 1. If use_count returns 1, + * there are no other owners. + * + * @return The number of Shared_pointer instances managing the current object or ​0​ if there is no managed + * object. */ - int use_count() const + auto use_count() const -> std::size_t { if (pointer != nullptr) { @@ -175,34 +178,59 @@ namespace teachos::arch::stl } /** - * @brief Checks if this is the only shared pointer managing the object. + * @brief Checks whether *this owns an object, i.e. whether get() != nullptr. * - * @return True if the use count is 1, otherwise false. + * @return true if *this owns an object, false otherwise. */ - bool unique() const { return use_count() == 1; } + explicit operator bool() const { return pointer != nullptr; } /** - * @brief Checks if the shared pointer is not empty. - * - * @return True if the pointer is not null, otherwise false. + * @brief Defaulted three-way comparator operator. */ - explicit operator bool() const { return pointer != nullptr; } + auto operator<=>(const shared_pointer & other) const = default; private: - T * pointer; ///< The managed object. - std::atomic * ref_count; ///< Reference count. + /** + * @brief Releases ownership and deletes the object if this was the last ereference to the owned managed object. + */ + auto cleanup() -> void + { + if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0) + { + delete pointer; + delete ref_count; + } + } + + T * pointer; ///< The managed object. + std::atomic * ref_count; ///< Reference count. }; /** - * @brief Creates a shared pointer instance. + * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls + * lhs.swap(rhs). + * + * @tparam T Type of the managed object. + * @param lhs, rhs Smart pointers whose contents to swap. + */ + template + auto swap(shared_pointer & lhs, shared_pointer & rhs) -> void + { + lhs.swap(rhs); + } + + /** + * @brief Constructs an object of type T and wraps it in a shared_pointer. Constructs a non-array type T. The + * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is + * not an array type. The function is equivalent to: shared_pointer(new T(std::forward(args)...)). * - * @tparam T The type of object to allocate. - * @tparam Args Argument types for the constructor of T. - * @param args Arguments for the constructor of T. - * @return A shared_pointer instance managing a newly created object. + * @tparam T Type of the managed object. + * @tparam Args Argument types for T's constructor. + * @param args List of arguments with which an instance of T will be constructed. + * @returns Shared_pointer of an instance of type T. */ template - shared_pointer make_shared(Args &&... args) + auto make_shared(Args &&... args) -> shared_pointer { return shared_pointer(new T(std::forward(args)...)); } diff --git a/arch/x86_64/include/arch/stl/unique_pointer.hpp b/arch/x86_64/include/arch/stl/unique_pointer.hpp index 08c862d..899a35b 100644 --- a/arch/x86_64/include/arch/stl/unique_pointer.hpp +++ b/arch/x86_64/include/arch/stl/unique_pointer.hpp @@ -4,7 +4,8 @@ namespace teachos::arch::stl { /** - * @brief A simple unique pointer implementation. + * @brief Unique_pointer is a smart pointer that owns (is responsible for) and manages another object via a pointer + * and subsequently disposes of that object when the unique_pointer goes out of scope. * * @tparam T Type of the managed object. */ @@ -12,13 +13,14 @@ namespace teachos::arch::stl struct unique_pointer { /** - * @brief Constructs a unique pointer. + * @brief Constructor. * - * @param ptr Pointer to manage, default is nullptr. + * @param ptr A pointer to an object to manage (default is nullptr). */ explicit unique_pointer(T * ptr = nullptr) : pointer(ptr) { + // Nothing to do. } /** @@ -34,7 +36,7 @@ namespace teachos::arch::stl /** * @brief Deleted copy assignment operator to enforce unique ownership. */ - unique_pointer & operator=(const unique_pointer &) = delete; + auto operator=(const unique_pointer &) -> unique_pointer & = delete; /** * @brief Move constructor. @@ -48,12 +50,12 @@ namespace teachos::arch::stl } /** - * @brief Move assignment operator. + * @brief Move assignment operator. Transfers ownership from other to *this as if by calling reset(r.release()). * - * @param other Unique pointer to move from. + * @param other Smart pointer from which ownership will be transferred. * @return Reference to this unique pointer. */ - unique_pointer & operator=(unique_pointer && other) noexcept + auto operator=(unique_pointer && other) noexcept -> unique_pointer & { if (this != &other) { @@ -65,32 +67,42 @@ namespace teachos::arch::stl } /** - * @brief Dereference operator. + * @brief Dereference operator. If get() is a null pointer, the behavior is undefined. * - * @return Reference to the managed object. + * @return Returns the object owned by *this, equivalent to *get(). */ - T & operator*() const { return *pointer; } + auto operator*() const -> T & { return *pointer; } /** * @brief Member access operator. * - * @return Pointer to the managed object. + * @return Returns a pointer to the object owned by *this, i.e. get(). + */ + auto operator->() const -> T * { return pointer; } + + /** + * @brief Returns a pointer to the managed object or nullptr if no object is owned. + * + * @return Pointer to the managed object or nullptr if no object is owned. */ - T * operator->() const { return pointer; } + auto get() const -> T * { return pointer; } /** - * @brief Gets the raw pointer. + * @brief Checks whether *this owns an object, i.e. whether get() != nullptr. * - * @return The managed pointer. + * @return true if *this owns an object, false otherwise. */ - T * get() const { return pointer; } + explicit operator bool() const noexcept { return pointer != nullptr; } /** - * @brief Releases ownership of the managed object. + * @brief Releases the ownership of the managed object, if any. + * get() returns nullptr after the call. + * The caller is responsible for cleaning up the object (e.g. by use of get_deleter()). * - * @return The raw pointer and sets internal pointer to nullptr. + * @return Pointer to the managed object or nullptr if there was no managed object, i.e. the value which would be + * returned by get() before the call. */ - T * release() + auto release() -> T * { T * temp = pointer; pointer = nullptr; @@ -98,37 +110,65 @@ namespace teachos::arch::stl } /** - * @brief Resets the managed object. + * @brief Replaces the managed object. * - * @param ptr New pointer to manage (default is nullptr). + * @note A test for self-reset, i.e. whether ptr points to an object already managed by *this, is not performed, + * except where provided as a compiler extension or as a debugging assert. Note that code such as + * p.reset(p.release()) does not involve self-reset, only code like p.reset(p.get()) does. + * + * @param ptr Pointer to a new object to manage (default = nullptr). */ - void reset(T * ptr = nullptr) + auto reset(T * ptr = nullptr) -> void { delete pointer; pointer = ptr; } /** - * @brief Swaps the managed object with another unique pointer. + * @brief Swaps the managed objects and associated deleters of *this and another unique_ptr object other. * - * @param other Unique pointer to swap with. + * @param other Another unique_ptr object to swap the managed object and the deleter with. */ - void swap(unique_pointer & other) { std::swap(pointer, other.pointer); } + auto swap(unique_pointer & other) -> void + { + using std::swap; + swap(pointer, other.pointer); + } + + /** + * @brief Defaulted three-way comparator operator. + */ + auto operator<=>(const unique_pointer & other) const = default; private: T * pointer; ///< The managed pointer. }; /** - * @brief Creates a unique pointer instance. + * @brief Specializes the std::swap algorithm for stl::unique_ptr. Swaps the contents of lhs and rhs. Calls + * lhs.swap(rhs). + * + * @tparam T Type of the managed object. + * @param lhs, rhs Smart pointers whose contents to swap. + */ + template + auto swap(unique_pointer & lhs, unique_pointer & rhs) -> void + { + lhs.swap(rhs); + } + + /** + * @brief Constructs an object of type T and wraps it in a unique_pointer. Constructs a non-array type T. The + * arguments args are passed to the constructor of T. This overload participates in overload resolution only if T is + * not an array type. The function is equivalent to: unique_pointer(new T(std::forward(args)...)). * * @tparam T Type of the managed object. * @tparam Args Argument types for T's constructor. - * @param args Arguments for T's constructor. - * @return A unique pointer managing a newly created T object. + * @param args List of arguments with which an instance of T will be constructed. + * @returns Unique_pointer of an instance of type T. */ template - unique_pointer make_unique(Args &&... args) + auto make_unique(Args &&... args) -> unique_pointer { return unique_pointer(new T(std::forward(args)...)); } diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index 5bebf62..b8bedf3 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -29,7 +29,7 @@ namespace teachos::arch::stl * @param capacity Amount of elements we want to create and set the given value for. * @param initial Inital value of all elements in the underlying data array. */ - explicit vector(size_t capacity, T initial = T{}) + explicit vector(std::size_t capacity, T initial = T{}) : _size(capacity) , _capacity(capacity) , _data(new T[_capacity]{}) @@ -113,7 +113,7 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - size_t size() const { return _size; } + std::size_t size() const { return _size; } /** * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we @@ -121,7 +121,7 @@ namespace teachos::arch::stl * * @return Current amount of space the vector has for elements. */ - size_t capacity() const { return _capacity; } + std::size_t capacity() const { return _capacity; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -131,7 +131,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & operator[](size_t index) { return _data[index]; } + T & operator[](std::size_t index) { return _data[index]; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -141,7 +141,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & at(size_t index) + T & at(std::size_t index) { if (index >= _size) { @@ -357,7 +357,7 @@ namespace teachos::arch::stl * * @param new_capacity New capacity of the vector, in number of elements */ - void reserve(size_t new_capacity) + void reserve(std::size_t new_capacity) { if (new_capacity <= _capacity) { @@ -392,9 +392,9 @@ namespace teachos::arch::stl } private: - size_t _size = {}; ///< Amount of elements in the underlying data container - size_t _capacity = {}; ///< Amount of space for elements in the underlying data container - T * _data = {}; ///< Pointer to the first element in the underlying data container + std::size_t _size = {}; ///< Amount of elements in the underlying data container + std::size_t _capacity = {}; ///< Amount of space for elements in the underlying data container + T * _data = {}; ///< Pointer to the first element in the underlying data container }; } // namespace teachos::arch::stl -- 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.hpp | 60 +++++++--------- .../descriptor_table/gdt_flags.hpp | 49 ++++++++------ .../descriptor_table/segment_descriptor.hpp | 2 - .../descriptor_table/segment_descriptor_type.hpp | 27 ++++++++ .../descriptor_table/type_field.hpp | 79 ++++++++++++++++++++++ 5 files changed, 157 insertions(+), 60 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp index 36b22ce..c510170 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp @@ -2,21 +2,16 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP +#include "arch/context_switching/descriptor_table/type_field.hpp" + #include -#include -#include namespace teachos::arch::context_switching::descriptor_table { - enum class privilege_level - { - KERNEL = 0, - ADMIN = 1, - PRIVILEGED_USER = 2, - USER = 3 - }; - - /// @brief Defines the access byte of a Descriptor Table + /** + * @brief Defines helper function for all states that the access byte field of a segment descriptor can + * have. + */ struct access_byte { /** @@ -24,21 +19,17 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - PRESENT = 1U << 0U, ///< Present bit; Allows an entry to refer to a valid segment. - ///< Must be set (1) for any valid segment. - PRIVILEGE_LEVEL = 1U << 1U | 1 << 2U, ///< Descriptor privilege level field. - ///< Contains the CPU Privilege level of the segment. - DESCRIPTOR_TYPE = 1U << 3U, ///< Defines a system segment (if 0) or a code/data segment (if 1). - EXECUTABLE = 1U << 4U, ///< Defines a data segment (if 0) or a code segment which can be executed from (if 1). - CONFORMING = 1U << 5U, ///< For data selectors: Direction bit - ///< Grows up (if 0), grows down (if 1) - ///< For code selectors: Conforming bit - ///< Code can only be executed from the DPL ring (if 0) - ///< Code can be executed from equal or lower DPL ring (if 1) - READ_WRITE = 1U << 6U, ///< For code segments: Readable bit - ///< For data segments: Writeable bit (read is always allowed) - ACCESSED = 1U << 7U ///< Set, when the segment is accessed. If GDT descriptor is stored in read only pages and - ///< this bit is set to 0, the CPU trying to set this bit will trigger a page fault. + PRESENT = 1U << 0U, ///< Present bit; Allows an entry to refer to a valid segment. + ///< Must be set (1) for any valid segment. + ACCESS_LEVEL_KERNEL = 0, ///< Highest privileged level used by the kernel to allow for full access of resources. + ACCESS_LEVEL_ADMIN = + 2, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + ACCESS_LEVEL_PRIVILEGED_USER = + 4, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more than + ///< two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + ACCESS_LEVEL_USER = 6, ///< Restricts access to only application and their specific memory. + DESCRIPTOR_TYPE = 1U << 3U, ///< Defines a system segment (if 0) or a code/data segment (if 1). }; /** @@ -47,11 +38,7 @@ namespace teachos::arch::context_switching::descriptor_table * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to * allow reading the state of single bits more easily. */ - explicit access_byte(uint8_t flags) - : flags(flags) - { - // Nothing to do - } + access_byte(uint8_t flags); /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. @@ -62,14 +49,14 @@ namespace teachos::arch::context_switching::descriptor_table * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. */ - auto contains_flags(std::bitset<8U> other) const -> bool; + auto contains_flags(std::bitset<4U> other) const -> bool; /** - * @brief Returns the privilege level of the current access_byte + * @brief Returns the type field of the access byte. * - * @return privilege_level + * @return Copy of the underlying type field bits. */ - auto get_privilege_level() const -> privilege_level; + auto get_type_field() const -> type_field; /** * @brief Allows to compare the underlying std::bitset of two instances. @@ -80,7 +67,8 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(access_byte const & other) const -> bool = default; private: - std::bitset<8U> flags; ///< Underlying bitset used to read the flags from + std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. + type_field _type; ///< Field specifying the type of the segment descriptor and its settings. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp index 83a7c06..ef8f2fa 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp @@ -1,16 +1,15 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP + +#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" #include -#include namespace teachos::arch::context_switching::descriptor_table { /** - * @brief Defines helper function for all states that the global descriptor flags of a segment descriptor can + * @brief Defines helper function for all states that the flags field of a segment descriptor can * have. - * - * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information. */ struct gdt_flags { @@ -19,27 +18,33 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - GRANULARITY = 1U << 0U, ///< Indicates the size the Limit value in the segement descriptor is scaled by 1 Byte - ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. - PROTECTED_MODE_SEGMENT_16_OR_32_BIT_SIZE = 1U << 1U, ///< Descriptor defines either a 16-bit protected mdoe - ///< segment if bit is not set or 32-bit if the bit is set. - ENABLE_LONG_MODE = 1U << 2U ///< If set the descriptor defines a 64-bit code segment, when set - ///< PROTECTED_MODE_SEGMENT_16_OR_32_BIT_SIZE should always be clear. For other types - ///< of segments bit should not be set. + GRANULARITY = 1U << 0U, ///< Indicates the size the Limit value in the segement descriptor is scaled by 1 Byte + ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. + DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and + ///< operands. Enable for 32 bit, 16 bit otherwise. + STACK_POINTER_SIZE = 1U << 1U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for + ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. + UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 + ///< GiB, 4 KiB otherwise. + LENGTH = 1U << 2U ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment contains + ///< 64-bit code. Otherwise this bit should always be 0. Enable if instructions are executed in + ///< 64-bit code, otherwis they are executed in compatability 32-bit mode. If bis is set the + ///< DEFAULT_LENGTH bis needs to be 0 }; /** * @brief Constructor. * * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to - * allow reading the state of single bits more easily. Only the first 3 bit of the value will actually be converted - * into the std::bitset, because the latter 4 bits are not relevant and the 4th bit is reserved. + * allow reading the state of single bits more easily. Only the rightmost 3 bit of the value will actually be + * converted into the std::bitset, because the leftmost 4 bit are irrelevant and the 4th bit is reserved. + * + * @param type Depending on the segment descriptor type some of the passed bits are ignored. For system segment only + * the first bit Granularity is relevant, for the data segment the 3rd bit Length is irrelevant and for the code + * segment all bits are relevant. Bits that are not relevant will simply not be read and saved into the underlying + * flags std::bitset. */ - explicit gdt_flags(uint8_t flags) - : flags(flags >> 5U) - { - // Nothing to do - } + gdt_flags(uint8_t flags, segment_descriptor_type type); /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. @@ -61,8 +66,8 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(gdt_flags const & other) const -> bool = default; private: - std::bitset<4U> flags; ///< Underlying bitset used to read the flags from. + std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. }; } // namespace teachos::arch::context_switching::descriptor_table -#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index 8428dfa..b7665d9 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -4,8 +4,6 @@ #include "arch/context_switching/descriptor_table/gdt_flags.hpp" #include -#include -#include namespace teachos::arch::context_switching::descriptor_table { diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp new file mode 100644 index 0000000..4815fca --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP + +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + /** + * @brief Possible overlying types of the segment descriptor. Allowing to discern between the major types, which + * result in different handling of the actual data contained in the descriptor. + */ + enum class segment_descriptor_type : uint8_t + { + SYSTEM_SEGMENT, ///< The segment is of type system, is distinguished by the Descriptor Type field in the Access + ///< Byte. Can be further distinguised to specific system segment types using the Type Field in the + ///< Access Byte. + DATA_SEGMENT, ///< The segment is of type data, is is distinguished by the Descriptor Type field in the Access + ///< Byte and the first bit of the Type Field in the Access Byte. Can be further distinguised to + ///< specific data segment types using the the remaining bits in the Type Field in the Access Byte. + CODE_SEGMENT, ///< The segment is of type code, is is distinguished by the Descriptor Type field in + ///< the Access Byte and the first bit of the Type Field in the Access Byte. Can be + ///< further distinguised to specific data segment types using the the remaining bits in + ///< the Type Field in the Access Byte. + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp new file mode 100644 index 0000000..88e25cf --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp @@ -0,0 +1,79 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TYPE_FIELD_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TYPE_FIELD_HPP + +#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" + +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + /** + * @brief Defines helper function for all states that the flags field of a segment descriptor can + * have. + */ + struct type_field + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + TYPE = 1U << 0U, ///< Further defines the actual type of the segment. If enabled this segment is a code segment, + ///< otherwise its a data segment. + EXPAND_UP = 1U << 1U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the + ///< data segment expands downwards, otherwise it expands upwards. + CONFORMING = + 1U << 1U, ///< Indicates if the code is allowed to be executed by different access levels + ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise + ///< access from different privilege levels with throw a General-Protectione exception. + WRITABLE = 1U << 2U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows + ///< read and write access, otherwise only read access is possible. + READABLE = 1U << 2U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows + ///< read and execute access, otherwise only executable access is possible. + ACCESSED = + 1U + << 3U, ///< Whether the segment has been accessed since the last time the operating system has cleared the + ///< flag. If enabled it has been accessed, otherwise it has not been accessed since the last clear. + LOCAL_DESCRIPTOR_TABLE = 2, ///< The actual type of sytem segment is a local descriptor table. + TASK_STATE_SEGMENT_AVAILABLE = + 9, ///< The actual type of sytem segment is a task state segment that is still available. + TASK_STATE_SEGMENT_BUSY = 11, ///< The actual type of sytem segment is a task state segment that is currently in + ///< use and therefore busy. + CALL_GATE = 11, ///< The actual type of sytem segment is a call gate. + INTERRUPT_GATE = 14, ///< The actual type of sytem segment is a interrupt gate. + TRAP_GATE = 15 ///< The actual type of sytem segment is a trap gate. + }; + + /** + * @brief Constructor. + * + * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to + * allow reading the state of single bits more easily. + */ + type_field(uint8_t flags); + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + */ + auto contains_flags(std::bitset<4U> other) const -> bool; + + /** + * @brief Allows to compare the underlying std::bitset of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying std::bitset of both types is the same. + */ + auto operator==(type_field const & other) const -> bool = default; + + private: + std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TYPE_FIELD_HPP -- 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.hpp | 54 +++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index b7665d9..59f99f6 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -1,44 +1,44 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP +#include "arch/context_switching/descriptor_table/access_byte.hpp" #include "arch/context_switching/descriptor_table/gdt_flags.hpp" - -#include +#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" +#include "arch/context_switching/descriptor_table/type_field.hpp" namespace teachos::arch::context_switching::descriptor_table { + __extension__ typedef __int128 int128_t; + __extension__ typedef unsigned __int128 uint128_t; - /* - TODO: Lookup segment_descriptor in intel manual chapter 3.4.5 - */ - + /** + * @brief Defines helper function for all states and the actual data the segment descriptor can have. + */ struct segment_descriptor { /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + * @brief Constructor. + * + * @note Created segment descriptor copies the given bytes into theese components ending with a 32 bit reserved + * field that has to be used, because the 64-bit segment descriptor needs to be big enough for two 32-bit segment + * descriptor. + * - 8 bit Access Type + * - 4 bit Flags + * - 64 bit Base Address + * - 20 bit Limit + * + * @param flags Copies the bits set from the given data into the individual components of a segment + * descriptor. */ - enum bitset : uint64_t - { - BASE = 1U << 0U, - FLAGS = 1U << 8U, - LIMIT = 1U << 12U, - ACCESS_BYTE = 1U << 16U, - BASE = 1U << 32U, - BASE = 1U << 40U, - LIMIT = 1U << 56U - }; - - explicit segment_descriptor(uint64_t flags) - : flags(flags) - { - // Nothing to do - } + explicit segment_descriptor(uint128_t flags); private: - std::uint8_t base1; - gdt_flags flags; - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from + uint32_t _reserved; + access_byte _access; + gdt_flags _flag; + uint64_t _base; + std::bitset<20U> _limit; }; } // namespace teachos::arch::context_switching::descriptor_table -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP -- 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 --- .../arch/context_switching/descriptor_table/access_byte.hpp | 4 ++-- .../include/arch/context_switching/descriptor_table/gdt_flags.hpp | 7 +------ .../context_switching/descriptor_table/segment_descriptor.hpp | 5 +++++ .../arch/context_switching/descriptor_table/type_field.hpp | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp index c510170..d1b579d 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp @@ -28,8 +28,8 @@ namespace teachos::arch::context_switching::descriptor_table ACCESS_LEVEL_PRIVILEGED_USER = 4, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more than ///< two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_USER = 6, ///< Restricts access to only application and their specific memory. - DESCRIPTOR_TYPE = 1U << 3U, ///< Defines a system segment (if 0) or a code/data segment (if 1). + ACCESS_LEVEL_USER = 6, ///< Restricts access to only application and their specific memory. + CODE_OR_DATA_SEGMENT = 1U << 3U, ///< Defines a system segment (if 0) or a code/data segment (if 1). }; /** diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp index ef8f2fa..bc6ecb7 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp @@ -38,13 +38,8 @@ namespace teachos::arch::context_switching::descriptor_table * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to * allow reading the state of single bits more easily. Only the rightmost 3 bit of the value will actually be * converted into the std::bitset, because the leftmost 4 bit are irrelevant and the 4th bit is reserved. - * - * @param type Depending on the segment descriptor type some of the passed bits are ignored. For system segment only - * the first bit Granularity is relevant, for the data segment the 3rd bit Length is irrelevant and for the code - * segment all bits are relevant. Bits that are not relevant will simply not be read and saved into the underlying - * flags std::bitset. */ - gdt_flags(uint8_t flags, segment_descriptor_type type); + gdt_flags(uint8_t flags); /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index 59f99f6..364e546 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -32,6 +32,11 @@ namespace teachos::arch::context_switching::descriptor_table */ explicit segment_descriptor(uint128_t flags); + /** + * @brief Calculates the underlying segment type that this segement descriptor is describing. + */ + auto get_segment_type() const -> segment_descriptor_type; + private: uint32_t _reserved; access_byte _access; diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp index 88e25cf..da61d38 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp @@ -18,10 +18,10 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - TYPE = 1U << 0U, ///< Further defines the actual type of the segment. If enabled this segment is a code segment, - ///< otherwise its a data segment. - EXPAND_UP = 1U << 1U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the - ///< data segment expands downwards, otherwise it expands upwards. + CODE_SEGMENT = 1U << 0U, ///< Further defines the actual type of the segment. If enabled this segment is a code + ///< segment, otherwise its a data segment. + EXPAND_UP = 1U << 1U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the + ///< data segment expands downwards, otherwise it expands upwards. CONFORMING = 1U << 1U, ///< Indicates if the code is allowed to be executed by different access levels ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise -- 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.hpp | 23 +++++++++------ .../descriptor_table/gdt_flags.hpp | 27 ++++++++++-------- .../descriptor_table/segment_descriptor.hpp | 23 +++++++++++---- .../descriptor_table/type_field.hpp | 33 +++++++++++++--------- arch/x86_64/include/arch/stl/vector.hpp | 2 +- 5 files changed, 68 insertions(+), 40 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp index d1b579d..dc4de03 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp @@ -19,8 +19,7 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - PRESENT = 1U << 0U, ///< Present bit; Allows an entry to refer to a valid segment. - ///< Must be set (1) for any valid segment. + CODE_OR_DATA_SEGMENT = 1U << 0U, ///< Defines a system segment (if 0) or a code/data segment (if 1). ACCESS_LEVEL_KERNEL = 0, ///< Highest privileged level used by the kernel to allow for full access of resources. ACCESS_LEVEL_ADMIN = 2, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more @@ -28,17 +27,23 @@ namespace teachos::arch::context_switching::descriptor_table ACCESS_LEVEL_PRIVILEGED_USER = 4, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more than ///< two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_USER = 6, ///< Restricts access to only application and their specific memory. - CODE_OR_DATA_SEGMENT = 1U << 3U, ///< Defines a system segment (if 0) or a code/data segment (if 1). + ACCESS_LEVEL_USER = 6, ///< Restricts access to only application and their specific memory. + PRESENT = 1U << 3U, ///< Present bit; Allows an entry to refer to a valid segment. + ///< Must be set (1) for any valid segment. }; + /** + * @brief Default Constructor. + */ + access_byte() = default; + /** * @brief Constructor. * - * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to - * allow reading the state of single bits more easily. + * @param flags Left-most four bits of the access_byte. + * @param type_field Right-most four bits of the access_byte representing the type_field. */ - access_byte(uint8_t flags); + access_byte(uint8_t flags, uint8_t type_field); /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. @@ -67,8 +72,8 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(access_byte const & other) const -> bool = default; private: - std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. - type_field _type; ///< Field specifying the type of the segment descriptor and its settings. + std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. + type_field _type = {}; ///< Field specifying the type of the segment descriptor and its settings. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp index bc6ecb7..f27284e 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp @@ -18,20 +18,25 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - GRANULARITY = 1U << 0U, ///< Indicates the size the Limit value in the segement descriptor is scaled by 1 Byte - ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. - DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and - ///< operands. Enable for 32 bit, 16 bit otherwise. - STACK_POINTER_SIZE = 1U << 1U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for - ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. + LENGTH = 1U << 0U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment + ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions are + ///< executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. If bis + ///< is set the DEFAULT_LENGTH bis needs to be 0 UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 ///< GiB, 4 KiB otherwise. - LENGTH = 1U << 2U ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment contains - ///< 64-bit code. Otherwise this bit should always be 0. Enable if instructions are executed in - ///< 64-bit code, otherwis they are executed in compatability 32-bit mode. If bis is set the - ///< DEFAULT_LENGTH bis needs to be 0 + STACK_POINTER_SIZE = 1U << 1U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for + ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. + DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and + ///< operands. Enable for 32 bit, 16 bit otherwise. + GRANULARITY = 1U << 2U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte + ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. }; + /** + * @brief Default Constructor. + */ + gdt_flags() = default; + /** * @brief Constructor. * @@ -61,7 +66,7 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(gdt_flags const & other) const -> bool = default; private: - std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. + std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index 364e546..b5697e3 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -16,6 +16,11 @@ namespace teachos::arch::context_switching::descriptor_table */ struct segment_descriptor { + /** + * @brief Default Constructor. + */ + segment_descriptor() = default; + /** * @brief Constructor. * @@ -32,17 +37,25 @@ namespace teachos::arch::context_switching::descriptor_table */ explicit segment_descriptor(uint128_t flags); + /** + * @brief Constructor. + * + * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of + * a segment descriptor. + */ + segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit); + /** * @brief Calculates the underlying segment type that this segement descriptor is describing. */ auto get_segment_type() const -> segment_descriptor_type; private: - uint32_t _reserved; - access_byte _access; - gdt_flags _flag; - uint64_t _base; - std::bitset<20U> _limit; + uint32_t _reserved = {}; + access_byte _access = {}; + gdt_flags _flag = {}; + uint64_t _base = {}; + std::bitset<20U> _limit = {}; }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp index da61d38..3822f9c 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp @@ -18,22 +18,22 @@ namespace teachos::arch::context_switching::descriptor_table */ enum bitset : uint8_t { - CODE_SEGMENT = 1U << 0U, ///< Further defines the actual type of the segment. If enabled this segment is a code - ///< segment, otherwise its a data segment. - EXPAND_UP = 1U << 1U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the - ///< data segment expands downwards, otherwise it expands upwards. - CONFORMING = - 1U << 1U, ///< Indicates if the code is allowed to be executed by different access levels - ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise - ///< access from different privilege levels with throw a General-Protectione exception. - WRITABLE = 1U << 2U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows - ///< read and write access, otherwise only read access is possible. - READABLE = 1U << 2U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows - ///< read and execute access, otherwise only executable access is possible. ACCESSED = 1U - << 3U, ///< Whether the segment has been accessed since the last time the operating system has cleared the + << 0U, ///< Whether the segment has been accessed since the last time the operating system has cleared the ///< flag. If enabled it has been accessed, otherwise it has not been accessed since the last clear. + WRITABLE = 1U << 1U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows + ///< read and write access, otherwise only read access is possible. + READABLE = 1U << 1U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows + ///< read and execute access, otherwise only executable access is possible. + CONFORMING = + 1U << 2U, ///< Indicates if the code is allowed to be executed by different access levels + ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise + ///< access from different privilege levels with throw a General-Protectione exception. + EXPAND_DOWN = 1U << 2U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the + ///< data segment expands downwards, otherwise it expands upwards. + CODE_SEGMENT = 1U << 3U, ///< Further defines the actual type of the segment. If enabled this segment is a code + ///< segment, otherwise its a data segment. LOCAL_DESCRIPTOR_TABLE = 2, ///< The actual type of sytem segment is a local descriptor table. TASK_STATE_SEGMENT_AVAILABLE = 9, ///< The actual type of sytem segment is a task state segment that is still available. @@ -44,6 +44,11 @@ namespace teachos::arch::context_switching::descriptor_table TRAP_GATE = 15 ///< The actual type of sytem segment is a trap gate. }; + /** + * @brief Default Constructor. + */ + type_field() = default; + /** * @brief Constructor. * @@ -72,7 +77,7 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(type_field const & other) const -> bool = default; private: - std::bitset<4U> _flags; ///< Underlying bitset used to read the flags from. + std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index b8bedf3..112af57 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -18,7 +18,7 @@ namespace teachos::arch::stl struct vector { /** - * @brief Defaulted constructor. Initalizes empty vector. + * @brief Default Constructor. */ vector() = default; -- 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.hpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index b5697e3..06e2e8a 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -51,11 +51,14 @@ namespace teachos::arch::context_switching::descriptor_table auto get_segment_type() const -> segment_descriptor_type; private: - uint32_t _reserved = {}; - access_byte _access = {}; - gdt_flags _flag = {}; - uint64_t _base = {}; - std::bitset<20U> _limit = {}; + // The order in private variables starts for the first variable being the rightmost bit. + std::bitset<16U> _limit_1 = {}; ///< First part of the limit field (0 - 15) + std::bitset<24U> _base_1 = {}; ///< First part of the base field (16 - 39) + access_byte _access = {}; ///< Access byte field (40 - 47) + std::bitset<4U> _limit_2 = {}; ///< Second part of the limit field (48 - 51) + gdt_flags _flag = {}; ///< Flags field (52 - 55) + std::bitset<40U> _base_2 = {}; ///< Second part of the base field (56 - 95) + uint32_t _reserved = {}; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::descriptor_table -- 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.hpp | 19 ++++++ .../global_descriptor_table_pointer.hpp | 23 +++++++ .../include/arch/kernel/cpu/control_register.hpp | 71 ++++++++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/msr.hpp | 64 +++++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/ss.hpp | 56 +++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/tlb.hpp | 27 ++++++++ .../include/arch/memory/cpu/control_register.hpp | 71 ---------------------- arch/x86_64/include/arch/memory/cpu/msr.hpp | 64 ------------------- arch/x86_64/include/arch/memory/cpu/tlb.hpp | 27 -------- .../arch/memory/paging/active_page_table.hpp | 6 +- .../include/arch/memory/paging/kernel_mapper.hpp | 2 +- 11 files changed, 264 insertions(+), 166 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/control_register.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/msr.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/ss.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/tlb.hpp delete mode 100644 arch/x86_64/include/arch/memory/cpu/control_register.hpp delete mode 100644 arch/x86_64/include/arch/memory/cpu/msr.hpp delete mode 100644 arch/x86_64/include/arch/memory/cpu/tlb.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp index e69de29..daba1fe 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp @@ -0,0 +1,19 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP + +#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" +#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" +#include "arch/stl/vector.hpp" + +namespace teachos::arch::context_switching::descriptor_table +{ + typedef stl::vector global_descriptor_table; + + auto create_global_descriptor_table() -> global_descriptor_table; + + auto load_global_descriptor_table(global_descriptor_table_pointer gdt_pointer) -> void; + + auto initialize_global_descriptor_table() -> global_descriptor_table; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp new file mode 100644 index 0000000..c2925fd --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp @@ -0,0 +1,23 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP + +#include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" + +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + /** + * @brief Represents a pointer to the Global Descriptor Table (GDT). + * + * This structure is used to store the base address and length of the GDT. + * It is used when loading or modifying the GDT during context switching. + */ + struct global_descriptor_table_pointer + { + uint16_t table_length; ///< The size of the GDT in bytes. + global_descriptor_table * address; ///< Pointer to the GDT base address. + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/control_register.hpp b/arch/x86_64/include/arch/kernel/cpu/control_register.hpp new file mode 100644 index 0000000..27c7777 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/control_register.hpp @@ -0,0 +1,71 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP + +#include + +namespace teachos::arch::memory::cpu +{ + /** + * @brief Control registers that can be read and written to. + * + * @note CR1 and CR5 - 7 are reserved and will throw an exception if they are accessed, therefore they are not defined + * in the enum. See https://en.wikipedia.org/wiki/Control_register#Control_registers_in_Intel_x86_series for more + * information. + */ + enum struct control_register : uint8_t + { + CR0, ///< Contains various control flags that modify basic operation of the processor, Machine Status World (MSW) + ///< register. + CR2 = 2U, ///< Contains Page Fault Linear Address (PFLA), when page fault occurs address program attended to accces + ///< is stored here. + CR3, ///< Enables process to translate linear addresses into physical addresses using paging, CR0 bit 32 Paging + ///< (PG) needs to be enabled simply contains the register value that represents the physical address of the + ///< level 4 page table used for paging in the system. Therefore reading this value allows to access the level + ///< 4 page table directly. Instead of over the virtual address 0xffffffff'fffff000, which then has to be + ///< first translated into a physical address. + CR4 ///< Used in protected mode to control operations. + }; + + /** + * @brief Control register 0 flags that can be set. + * + * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest + * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information. + */ + enum struct cr0_flags : uint64_t + { + PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected or system is in real mode. + TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used. + WRITE_PROTECT = 1U << 16U, ///< When set, the CPU cannot write to read-only pages when privilege level is 0. + PAGING = 1U << 31U, // Enable paging using the CR3 register. + }; + + /** + * @brief Reads the value of the given control register. + * + * @param cr Control register that should be read. + * @return Value of the control register. + */ + auto read_control_register(control_register cr) -> uint64_t; + + /** + * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register. + * + * @param cr Control register that should be written. + * @param new_value New value that should be written. + */ + auto write_control_register(control_register cr, uint64_t new_value) -> void; + + /** + * @brief Sets a specific bit in the CR0. + * + * @note This function reads the current value of the CR0 register, ORs the specified + * bit with the current value, and writes the updated value back to the CR0. + * + * @param flag he flag to set in the CR0. + */ + auto set_cr0_bit(cr0_flags flag) -> void; + +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/msr.hpp b/arch/x86_64/include/arch/kernel/cpu/msr.hpp new file mode 100644 index 0000000..52d74bd --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/msr.hpp @@ -0,0 +1,64 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP + +#include +#include + +namespace teachos::arch::memory::cpu +{ + /** + * @brief Important flags that can be writen into the Extended Feature Enable Register (EFER). + * + * @note EFER is a model-specific register allowing to configure CPU extensions. Only the most important extensions + * are listed below, the rest are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#EFER for + * more information. + */ + enum class efer_flags : uint64_t + { + SCE = 1UL << 0UL, ///< System Call Extensions. + LME = 1UL << 8UL, ///< Long Mode Enabled. + LMA = 1UL << 10UL, ///< Long Mode Active. + NXE = 1UL << 11UL, ///< No-Execute Enable. + SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable. + LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable. + FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR. + TCE = 1UL << 15UL, ///< Translation Cache Extension. + }; + + /** + * @brief Reads a 64-bit from the Model-Specific Register (MSR). + * + * @note This function reads the value of an MSR specified by the given address. It combines the lower and upper + * 32-bits of the MSR value read using the 'rdmsr' instruction and returns it as a 64-bit unsigned integer. + * + * @param msr The address of the MSR to read. + * @return The 64-bit value read from the MSR. + */ + auto read_msr(uint32_t msr) -> uint64_t; + + /** + * @brief Writes a 64-bit value to a Model-Specific Register (MSR). + * + * @note This function writes a 64-bit value to the MSR specified by the given address. + * It splits the 64-bit value into two 32-bit parts and writes them using the + * `wrmsr` instruction. + * + * @param msr The address of the MSR to write to. + * @param new_value The 64-bit value to write to the MSR. + */ + auto write_msr(uint32_t msr, uint64_t new_value) -> void; + + /** + * @brief Sets a specific bit in the Extended Feature Enable Register (EFER), which is a Model-Specific Register + * (MSR). + * + * @note This function reads the current value of the EFER register, ORs the specified + * bit with the current value, and writes the updated value back to the EFER register. + * + * @param flag The flag to set in the EFER register. + */ + auto set_efer_bit(efer_flags flag) -> void; + +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/kernel/cpu/ss.hpp b/arch/x86_64/include/arch/kernel/cpu/ss.hpp new file mode 100644 index 0000000..2d3518e --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/ss.hpp @@ -0,0 +1,56 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP + +#include +#include + +namespace teachos::arch::memory::cpu +{ + /** + * @brief Represents a segment selector in the x86_64 architecture. + * + * A segment selector is a 16-bit identifier used to select a segment descriptor + * from the Global Descriptor Table (GDT) or the Local Descriptor Table (LDT). + * It contains an index, a table indicator (TI), and a requested privilege level (RPL). + */ + struct segment_selector + { + /** + * @brief Constructs a segment selector. + * + * @param index The index of the segment descriptor. + * @param table_indicator The table indicator (0 for GDT, 1 for LDT). + * @param requested_privilege_level The requested privilege level (0-3). + */ + segment_selector(uint16_t index, std::bitset<1U> table_indicator, std::bitset<2U> requested_privilege_level); + + /** + * @brief Converts the segment selector to a 16-bit value. + * + * @return uint16_t The 16-bit representation of the segment selector. + */ + auto to_uint16() const -> uint16_t; + + private: + uint16_t index; + std::bitset<1U> table_indicator; + std::bitset<2U> requested_privilege_level; + }; + + /** + * @brief Reads the current value of the stack segment (SS) register. + * + * @return uint16_t The current SS register value. + */ + auto read_ss() -> uint16_t; + + /** + * @brief Writes a new value to the stack segment (SS) register. + * + * @param selector The segment selector to be written to SS. + */ + auto write_ss(segment_selector selector) -> void; + +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/tlb.hpp b/arch/x86_64/include/arch/kernel/cpu/tlb.hpp new file mode 100644 index 0000000..333cd58 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/tlb.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP + +#include "arch/memory/paging/virtual_page.hpp" + +namespace teachos::arch::memory::cpu +{ + /** + * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. + * + * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for + * that page. + */ + auto tlb_flush(paging::virtual_address address) -> void; + + /** + * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables. + * + * @note Simply reassigns the CR3 register the value of the CR3 register, causing a flush of the TLB buffer, because + * the system has to assume that the location of the level 4 page table moved. + */ + auto tlb_flush_all() -> void; + +} // namespace teachos::arch::memory::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/control_register.hpp b/arch/x86_64/include/arch/memory/cpu/control_register.hpp deleted file mode 100644 index e11813d..0000000 --- a/arch/x86_64/include/arch/memory/cpu/control_register.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP - -#include - -namespace teachos::arch::memory::cpu -{ - /** - * @brief Control registers that can be read and written to. - * - * @note CR1 and CR5 - 7 are reserved and will throw an exception if they are accessed, therefore they are not defined - * in the enum. See https://en.wikipedia.org/wiki/Control_register#Control_registers_in_Intel_x86_series for more - * information. - */ - enum struct control_register : uint8_t - { - CR0, ///< Contains various control flags that modify basic operation of the processor, Machine Status World (MSW) - ///< register. - CR2 = 2U, ///< Contains Page Fault Linear Address (PFLA), when page fault occurs address program attended to accces - ///< is stored here. - CR3, ///< Enables process to translate linear addresses into physical addresses using paging, CR0 bit 32 Paging - ///< (PG) needs to be enabled simply contains the register value that represents the physical address of the - ///< level 4 page table used for paging in the system. Therefore reading this value allows to access the level - ///< 4 page table directly. Instead of over the virtual address 0xffffffff'fffff000, which then has to be - ///< first translated into a physical address. - CR4 ///< Used in protected mode to control operations. - }; - - /** - * @brief Control register 0 flags that can be set. - * - * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest - * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information. - */ - enum struct cr0_flags : uint64_t - { - PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected or system is in real mode. - TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used. - WRITE_PROTECT = 1U << 16U, ///< When set, the CPU cannot write to read-only pages when privilege level is 0. - PAGING = 1U << 31U, // Enable paging using the CR3 register. - }; - - /** - * @brief Reads the value of the given control register. - * - * @param cr Control register that should be read. - * @return Value of the control register. - */ - auto read_control_register(control_register cr) -> uint64_t; - - /** - * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register. - * - * @param cr Control register that should be written. - * @param new_value New value that should be written. - */ - auto write_control_register(control_register cr, uint64_t new_value) -> void; - - /** - * @brief Sets a specific bit in the CR0. - * - * @note This function reads the current value of the CR0 register, ORs the specified - * bit with the current value, and writes the updated value back to the CR0. - * - * @param flag he flag to set in the CR0. - */ - auto set_cr0_bit(cr0_flags flag) -> void; - -} // namespace teachos::arch::memory::cpu - -#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/memory/cpu/msr.hpp b/arch/x86_64/include/arch/memory/cpu/msr.hpp deleted file mode 100644 index cda70e2..0000000 --- a/arch/x86_64/include/arch/memory/cpu/msr.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP - -#include -#include - -namespace teachos::arch::memory::cpu -{ - /** - * @brief Important flags that can be writen into the Extended Feature Enable Register (EFER). - * - * @note EFER is a model-specific register allowing to configure CPU extensions. Only the most important extensions - * are listed below, the rest are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#EFER for - * more information. - */ - enum class efer_flags : uint64_t - { - SCE = 1UL << 0UL, ///< System Call Extensions. - LME = 1UL << 8UL, ///< Long Mode Enabled. - LMA = 1UL << 10UL, ///< Long Mode Active. - NXE = 1UL << 11UL, ///< No-Execute Enable. - SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable. - LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable. - FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR. - TCE = 1UL << 15UL, ///< Translation Cache Extension. - }; - - /** - * @brief Reads a 64-bit from the Model-Specific Register (MSR). - * - * @note This function reads the value of an MSR specified by the given address. It combines the lower and upper - * 32-bits of the MSR value read using the 'rdmsr' instruction and returns it as a 64-bit unsigned integer. - * - * @param msr The address of the MSR to read. - * @return The 64-bit value read from the MSR. - */ - auto read_msr(uint32_t msr) -> uint64_t; - - /** - * @brief Writes a 64-bit value to a Model-Specific Register (MSR). - * - * @note This function writes a 64-bit value to the MSR specified by the given address. - * It splits the 64-bit value into two 32-bit parts and writes them using the - * `wrmsr` instruction. - * - * @param msr The address of the MSR to write to. - * @param new_value The 64-bit value to write to the MSR. - */ - auto write_msr(uint32_t msr, uint64_t new_value) -> void; - - /** - * @brief Sets a specific bit in the Extended Feature Enable Register (EFER), which is a Model-Specific Register - * (MSR). - * - * @note This function reads the current value of the EFER register, ORs the specified - * bit with the current value, and writes the updated value back to the EFER register. - * - * @param flag The flag to set in the EFER register. - */ - auto set_efer_bit(efer_flags flag) -> void; - -} // namespace teachos::arch::memory::cpu - -#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_NXE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/memory/cpu/tlb.hpp b/arch/x86_64/include/arch/memory/cpu/tlb.hpp deleted file mode 100644 index 075d7bb..0000000 --- a/arch/x86_64/include/arch/memory/cpu/tlb.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_TLB_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_CPU_TLB_HPP - -#include "arch/memory/paging/virtual_page.hpp" - -namespace teachos::arch::memory::cpu -{ - /** - * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained - * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. - * - * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for - * that page. - */ - auto tlb_flush(paging::virtual_address address) -> void; - - /** - * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables. - * - * @note Simply reassigns the CR3 register the value of the CR3 register, causing a flush of the TLB buffer, because - * the system has to assume that the location of the level 4 page table moved. - */ - auto tlb_flush_all() -> void; - -} // namespace teachos::arch::memory::cpu - -#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_TLB_HPP diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 1b2aaed..9846a21 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -2,8 +2,8 @@ #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP #include "arch/exception_handling/assert.hpp" +#include "arch/kernel/cpu/tlb.hpp" #include "arch/memory/allocator/concept.hpp" -#include "arch/memory/cpu/tlb.hpp" #include "arch/memory/paging/virtual_page.hpp" #include @@ -75,8 +75,8 @@ namespace teachos::arch::memory::paging * @param flags A bitset of flags that configure the page table entry for this mapping. */ template - auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, - std::bitset<64U> flags) -> void + auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, std::bitset<64U> flags) + -> void { auto current_handle = active_handle; 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 74f1c14..b137736 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP -#include "arch/memory/cpu/control_register.hpp" +#include "arch/kernel/cpu/control_register.hpp" #include "arch/memory/paging/active_page_table.hpp" #include "arch/memory/paging/inactive_page_table.hpp" #include "arch/memory/paging/temporary_page.hpp" -- 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.hpp | 2 -- .../global_descriptor_table_pointer.hpp | 8 ++++---- .../include/arch/kernel/cpu/control_register.hpp | 4 ++-- arch/x86_64/include/arch/kernel/cpu/lgdt.hpp | 19 +++++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/msr.hpp | 4 ++-- arch/x86_64/include/arch/kernel/cpu/ss.hpp | 4 ++-- arch/x86_64/include/arch/kernel/cpu/tlb.hpp | 6 +++--- .../include/arch/memory/paging/active_page_table.hpp | 2 +- .../include/arch/memory/paging/kernel_mapper.hpp | 14 +++++++------- 9 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 arch/x86_64/include/arch/kernel/cpu/lgdt.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp index daba1fe..45f2d31 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp @@ -11,8 +11,6 @@ namespace teachos::arch::context_switching::descriptor_table auto create_global_descriptor_table() -> global_descriptor_table; - auto load_global_descriptor_table(global_descriptor_table_pointer gdt_pointer) -> void; - auto initialize_global_descriptor_table() -> global_descriptor_table; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp index c2925fd..0305bff 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp @@ -1,8 +1,6 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP -#include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" - #include namespace teachos::arch::context_switching::descriptor_table @@ -15,8 +13,10 @@ namespace teachos::arch::context_switching::descriptor_table */ struct global_descriptor_table_pointer { - uint16_t table_length; ///< The size of the GDT in bytes. - global_descriptor_table * address; ///< Pointer to the GDT base address. + std::size_t table_length; ///< The size of the GDT in bytes. + + // TODO: Would rather use global_descriptor_table *, but circular dependency + uint64_t address; ///< Pointer to the GDT base address. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/kernel/cpu/control_register.hpp b/arch/x86_64/include/arch/kernel/cpu/control_register.hpp index 27c7777..dcaf02d 100644 --- a/arch/x86_64/include/arch/kernel/cpu/control_register.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/control_register.hpp @@ -3,7 +3,7 @@ #include -namespace teachos::arch::memory::cpu +namespace teachos::arch::kernel::cpu { /** * @brief Control registers that can be read and written to. @@ -66,6 +66,6 @@ namespace teachos::arch::memory::cpu */ auto set_cr0_bit(cr0_flags flag) -> void; -} // namespace teachos::arch::memory::cpu +} // namespace teachos::arch::kernel::cpu #endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp b/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp new file mode 100644 index 0000000..633d460 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp @@ -0,0 +1,19 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_LGDT_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_LGDT_HPP + +#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" + +#include +#include + +namespace teachos::arch::kernel::cpu +{ + /** + * @brief Loads the global_descriptor_table_pointer into the global descriptor table register (GDTR). + */ + auto load_global_descriptor_table(context_switching::descriptor_table::global_descriptor_table_pointer gdt_pointer) + -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_LGDT_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/msr.hpp b/arch/x86_64/include/arch/kernel/cpu/msr.hpp index 52d74bd..99d6378 100644 --- a/arch/x86_64/include/arch/kernel/cpu/msr.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/msr.hpp @@ -4,7 +4,7 @@ #include #include -namespace teachos::arch::memory::cpu +namespace teachos::arch::kernel::cpu { /** * @brief Important flags that can be writen into the Extended Feature Enable Register (EFER). @@ -59,6 +59,6 @@ namespace teachos::arch::memory::cpu */ auto set_efer_bit(efer_flags flag) -> void; -} // namespace teachos::arch::memory::cpu +} // namespace teachos::arch::kernel::cpu #endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_NXE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/kernel/cpu/ss.hpp b/arch/x86_64/include/arch/kernel/cpu/ss.hpp index 2d3518e..1fb6448 100644 --- a/arch/x86_64/include/arch/kernel/cpu/ss.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/ss.hpp @@ -4,7 +4,7 @@ #include #include -namespace teachos::arch::memory::cpu +namespace teachos::arch::kernel::cpu { /** * @brief Represents a segment selector in the x86_64 architecture. @@ -51,6 +51,6 @@ namespace teachos::arch::memory::cpu */ auto write_ss(segment_selector selector) -> void; -} // namespace teachos::arch::memory::cpu +} // namespace teachos::arch::kernel::cpu #endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/tlb.hpp b/arch/x86_64/include/arch/kernel/cpu/tlb.hpp index 333cd58..f3e58a6 100644 --- a/arch/x86_64/include/arch/kernel/cpu/tlb.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/tlb.hpp @@ -3,7 +3,7 @@ #include "arch/memory/paging/virtual_page.hpp" -namespace teachos::arch::memory::cpu +namespace teachos::arch::kernel::cpu { /** * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained @@ -12,7 +12,7 @@ namespace teachos::arch::memory::cpu * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for * that page. */ - auto tlb_flush(paging::virtual_address address) -> void; + auto tlb_flush(memory::paging::virtual_address address) -> void; /** * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables. @@ -22,6 +22,6 @@ namespace teachos::arch::memory::cpu */ auto tlb_flush_all() -> void; -} // namespace teachos::arch::memory::cpu +} // namespace teachos::arch::kernel::cpu #endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 9846a21..9e91a8c 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -153,7 +153,7 @@ namespace teachos::arch::memory::paging } unmap_page_table_entry(allocator, page, current_handle); - cpu::tlb_flush(page.start_address()); + kernel::cpu::tlb_flush(page.start_address()); } private: 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 b137736..8d36fde 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -77,16 +77,16 @@ namespace teachos::arch::memory::paging auto remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page, active_page_table & active_table) -> void { - auto const backup = - allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); + auto const backup = allocator::physical_frame::containing_address( + kernel::cpu::read_control_register(kernel::cpu::control_register::CR3)); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - cpu::tlb_flush_all(); + kernel::cpu::tlb_flush_all(); map_elf_kernel_sections(active_table); page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); - cpu::tlb_flush_all(); + kernel::cpu::tlb_flush_all(); temporary_page.unmap_page(active_table); } @@ -99,12 +99,12 @@ namespace teachos::arch::memory::paging */ auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table { - auto const backup = - allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3)); + auto const backup = allocator::physical_frame::containing_address( + kernel::cpu::read_control_register(kernel::cpu::control_register::CR3)); auto const old_table = inactive_page_table{backup}; auto const new_address = new_table.page_table_level_4_frame.start_address(); - cpu::write_control_register(cpu::control_register::CR3, new_address); + kernel::cpu::write_control_register(kernel::cpu::control_register::CR3, new_address); return old_table; } -- 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 --- .../descriptor_table/global_descriptor_table.hpp | 4 ---- .../descriptor_table/global_descriptor_table_pointer.hpp | 11 +++++++---- .../descriptor_table/segment_descriptor.hpp | 14 +++++++------- 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp index 45f2d31..c4d0e30 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp @@ -2,13 +2,9 @@ #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP #include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" -#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" -#include "arch/stl/vector.hpp" namespace teachos::arch::context_switching::descriptor_table { - typedef stl::vector global_descriptor_table; - auto create_global_descriptor_table() -> global_descriptor_table; auto initialize_global_descriptor_table() -> global_descriptor_table; diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp index 0305bff..d4febe1 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp @@ -1,10 +1,15 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP +#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" +#include "arch/stl/vector.hpp" + #include namespace teachos::arch::context_switching::descriptor_table { + typedef stl::vector global_descriptor_table; + /** * @brief Represents a pointer to the Global Descriptor Table (GDT). * @@ -13,10 +18,8 @@ namespace teachos::arch::context_switching::descriptor_table */ struct global_descriptor_table_pointer { - std::size_t table_length; ///< The size of the GDT in bytes. - - // TODO: Would rather use global_descriptor_table *, but circular dependency - uint64_t address; ///< Pointer to the GDT base address. + std::size_t table_length; ///< The size of the GDT in bytes. + global_descriptor_table * address; ///< Pointer to the GDT base address. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index 06e2e8a..86b6c75 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -52,13 +52,13 @@ namespace teachos::arch::context_switching::descriptor_table private: // The order in private variables starts for the first variable being the rightmost bit. - std::bitset<16U> _limit_1 = {}; ///< First part of the limit field (0 - 15) - std::bitset<24U> _base_1 = {}; ///< First part of the base field (16 - 39) - access_byte _access = {}; ///< Access byte field (40 - 47) - std::bitset<4U> _limit_2 = {}; ///< Second part of the limit field (48 - 51) - gdt_flags _flag = {}; ///< Flags field (52 - 55) - std::bitset<40U> _base_2 = {}; ///< Second part of the base field (56 - 95) - uint32_t _reserved = {}; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) + uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) + std::bitset<24U> _base_1 = {}; ///< First part of the base field (16 - 39) + access_byte _access = {}; ///< Access byte field (40 - 47) + std::bitset<4U> _limit_2 = {}; ///< Second part of the limit field (48 - 51) + gdt_flags _flag = {}; ///< Flags field (52 - 55) + std::bitset<40U> _base_2 = {}; ///< Second part of the base field (56 - 95) + uint32_t _reserved = {}; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // 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.hpp | 67 +++++--- .../descriptor_table/gdt_flags.hpp | 25 ++- .../global_descriptor_table_pointer.hpp | 22 ++- .../descriptor_table/segment_descriptor.hpp | 16 +- .../descriptor_table/type_field.hpp | 84 --------- arch/x86_64/include/arch/kernel/cpu/lgdt.hpp | 11 +- .../arch/memory/allocator/physical_frame.hpp | 6 +- .../arch/memory/heap/linked_list_allocator.hpp | 4 +- .../arch/memory/multiboot/elf_symbols_section.hpp | 6 +- .../include/arch/memory/multiboot/memory_map.hpp | 6 +- .../include/arch/memory/paging/virtual_page.hpp | 2 +- arch/x86_64/include/arch/shared/container.hpp | 83 --------- .../arch/shared/contiguous_pointer_iterator.hpp | 190 --------------------- .../include/arch/shared/forward_value_iterator.hpp | 110 ------------ arch/x86_64/include/arch/shared/mutex.hpp | 57 ------- arch/x86_64/include/arch/stl/container.hpp | 83 +++++++++ .../arch/stl/contiguous_pointer_iterator.hpp | 190 +++++++++++++++++++++ .../include/arch/stl/forward_value_iterator.hpp | 110 ++++++++++++ arch/x86_64/include/arch/stl/mutex.hpp | 57 +++++++ 19 files changed, 549 insertions(+), 580 deletions(-) delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp delete mode 100644 arch/x86_64/include/arch/shared/container.hpp delete mode 100644 arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp delete mode 100644 arch/x86_64/include/arch/shared/forward_value_iterator.hpp delete mode 100644 arch/x86_64/include/arch/shared/mutex.hpp create mode 100644 arch/x86_64/include/arch/stl/container.hpp create mode 100644 arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp create mode 100644 arch/x86_64/include/arch/stl/forward_value_iterator.hpp create mode 100644 arch/x86_64/include/arch/stl/mutex.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp index dc4de03..bafce8d 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp @@ -2,9 +2,8 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP -#include "arch/context_switching/descriptor_table/type_field.hpp" - #include +#include namespace teachos::arch::context_switching::descriptor_table { @@ -12,24 +11,49 @@ namespace teachos::arch::context_switching::descriptor_table * @brief Defines helper function for all states that the access byte field of a segment descriptor can * have. */ - struct access_byte + struct [[gnu::packed]] access_byte { /** * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. */ enum bitset : uint8_t { - CODE_OR_DATA_SEGMENT = 1U << 0U, ///< Defines a system segment (if 0) or a code/data segment (if 1). - ACCESS_LEVEL_KERNEL = 0, ///< Highest privileged level used by the kernel to allow for full access of resources. + ACCESSED = + 1U + << 0U, ///< Whether the segment has been accessed since the last time the operating system has cleared the + ///< flag. If enabled it has been accessed, otherwise it has not been accessed since the last clear. + WRITABLE = 1U << 1U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows + ///< read and write access, otherwise only read access is possible. + READABLE = 1U << 1U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows + ///< read and execute access, otherwise only executable access is possible. + CONFORMING = + 1U << 2U, ///< Indicates if the code is allowed to be executed by different access levels + ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise + ///< access from different privilege levels with throw a General-Protectione exception. + EXPAND_DOWN = 1U << 2U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the + ///< data segment expands downwards, otherwise it expands upwards. + CODE_SEGMENT = 1U << 3U, ///< Further defines the actual type of the segment. If enabled this segment is a code + ///< segment, otherwise its a data segment. + LOCAL_DESCRIPTOR_TABLE = 2, ///< The actual type of sytem segment is a local descriptor table. + TASK_STATE_SEGMENT_AVAILABLE = + 9, ///< The actual type of sytem segment is a task state segment that is still available. + TASK_STATE_SEGMENT_BUSY = 11, ///< The actual type of sytem segment is a task state segment that is currently in + ///< use and therefore busy. + CALL_GATE = 11, ///< The actual type of sytem segment is a call gate. + INTERRUPT_GATE = 14, ///< The actual type of sytem segment is a interrupt gate. + TRAP_GATE = 15, ///< The actual type of sytem segment is a trap gate. + CODE_OR_DATA_SEGMENT = 1U << 4U, ///< Defines a system segment (if 0) or a code/data segment (if 1). + ACCESS_LEVEL_KERNEL = + 0U << 4U, ///< Highest privileged level used by the kernel to allow for full access of resources. ACCESS_LEVEL_ADMIN = - 2, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more - ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + 2U << 4U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. ACCESS_LEVEL_PRIVILEGED_USER = - 4, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more than - ///< two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_USER = 6, ///< Restricts access to only application and their specific memory. - PRESENT = 1U << 3U, ///< Present bit; Allows an entry to refer to a valid segment. - ///< Must be set (1) for any valid segment. + 4U << 4U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + ACCESS_LEVEL_USER = 6U << 4U, ///< Restricts access to only application and their specific memory. + PRESENT = 1U << 3U << 4U, ///< Present bit; Allows an entry to refer to a valid segment. + ///< Must be set (1) for any valid segment. }; /** @@ -40,10 +64,11 @@ namespace teachos::arch::context_switching::descriptor_table /** * @brief Constructor. * - * @param flags Left-most four bits of the access_byte. - * @param type_field Right-most four bits of the access_byte representing the type_field. + * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used + * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags + * are enabled or not using contains_flags method. */ - access_byte(uint8_t flags, uint8_t type_field); + access_byte(uint8_t flags); /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. @@ -54,14 +79,7 @@ namespace teachos::arch::context_switching::descriptor_table * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. */ - auto contains_flags(std::bitset<4U> other) const -> bool; - - /** - * @brief Returns the type field of the access byte. - * - * @return Copy of the underlying type field bits. - */ - auto get_type_field() const -> type_field; + auto contains_flags(std::bitset<8U> other) const -> bool; /** * @brief Allows to compare the underlying std::bitset of two instances. @@ -72,8 +90,7 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(access_byte const & other) const -> bool = default; private: - std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. - type_field _type = {}; ///< Field specifying the type of the segment descriptor and its settings. + uint8_t _flags = {}; ///< Underlying bitset used to read the flags from. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp index f27284e..11f5dd4 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp @@ -11,7 +11,7 @@ namespace teachos::arch::context_switching::descriptor_table * @brief Defines helper function for all states that the flags field of a segment descriptor can * have. */ - struct gdt_flags + struct [[gnu::packed]] gdt_flags { /** * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. @@ -40,11 +40,14 @@ namespace teachos::arch::context_switching::descriptor_table /** * @brief Constructor. * - * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to - * allow reading the state of single bits more easily. Only the rightmost 3 bit of the value will actually be - * converted into the std::bitset, because the leftmost 4 bit are irrelevant and the 4th bit is reserved. + * @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. This value is saved and can later be used to check whether certain flags are + * enabled or not using contains_flags method. + * @param limit Does not necessarily make sense in the gdt flags type, but because the flags alone are only 4 bit + * the type would still require the space for a complete bit. Therefore the 4 bit segment limit field before the + * flags field is included in this type to ensure we actually contain 8 bit of data. */ - gdt_flags(uint8_t flags); + gdt_flags(uint8_t flags, std::bitset<20U> limit); /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. @@ -57,6 +60,15 @@ namespace teachos::arch::context_switching::descriptor_table */ auto contains_flags(std::bitset<4U> other) const -> bool; + /** + * @brief Get part of the segment limit that is saved in the gdt flags. This does not necessarily make sense in this + * object, but it has to be included here because a struct can not be smaller than a full byte. Therefore we include + * the 4 bit segment limit field so that it results in a compelte byte with the addtional 4 bit of gdt flags. + * + * @return 4-bit limit segment + */ + auto get_limit() const -> std::bitset<4U>; + /** * @brief Allows to compare the underlying std::bitset of two instances. * @@ -66,7 +78,8 @@ namespace teachos::arch::context_switching::descriptor_table auto operator==(gdt_flags const & other) const -> bool = default; private: - std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. + uint8_t _limit_2 : 4 = {}; + uint8_t _flags : 4 = {}; ///< Underlying bitset used to read the flags from. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp index d4febe1..ed17be3 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp @@ -16,10 +16,26 @@ namespace teachos::arch::context_switching::descriptor_table * This structure is used to store the base address and length of the GDT. * It is used when loading or modifying the GDT during context switching. */ - struct global_descriptor_table_pointer + struct [[gnu::packed]] global_descriptor_table_pointer { - std::size_t table_length; ///< The size of the GDT in bytes. - global_descriptor_table * address; ///< Pointer to the GDT base address. + /** + * @brief Default constructor. + */ + global_descriptor_table_pointer() = default; + + /** + * @brief Constructor. + */ + global_descriptor_table_pointer(uint16_t table_length, global_descriptor_table * address); + + /** + * @brief Defaulted three-way comparsion operator. + */ + auto operator<=>(global_descriptor_table_pointer const & other) const -> std::strong_ordering = default; + + private: + uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. + global_descriptor_table * address = {}; ///< Non-owning pointer to the GDT base address. }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index 86b6c75..7106771 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -4,7 +4,6 @@ #include "arch/context_switching/descriptor_table/access_byte.hpp" #include "arch/context_switching/descriptor_table/gdt_flags.hpp" #include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" -#include "arch/context_switching/descriptor_table/type_field.hpp" namespace teachos::arch::context_switching::descriptor_table { @@ -14,7 +13,7 @@ namespace teachos::arch::context_switching::descriptor_table /** * @brief Defines helper function for all states and the actual data the segment descriptor can have. */ - struct segment_descriptor + struct [[gnu::packed]] segment_descriptor { /** * @brief Default Constructor. @@ -52,13 +51,12 @@ namespace teachos::arch::context_switching::descriptor_table private: // The order in private variables starts for the first variable being the rightmost bit. - uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) - std::bitset<24U> _base_1 = {}; ///< First part of the base field (16 - 39) - access_byte _access = {}; ///< Access byte field (40 - 47) - std::bitset<4U> _limit_2 = {}; ///< Second part of the limit field (48 - 51) - gdt_flags _flag = {}; ///< Flags field (52 - 55) - std::bitset<40U> _base_2 = {}; ///< Second part of the base field (56 - 95) - uint32_t _reserved = {}; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) + uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) + uint32_t _base_1 : 24 = {}; ///< First part of the base field (16 - 39) + access_byte _access = {}; ///< Access byte field (40 - 47) + gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55) + uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) + uint32_t _reserved = {}; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp deleted file mode 100644 index 3822f9c..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/type_field.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TYPE_FIELD_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TYPE_FIELD_HPP - -#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - /** - * @brief Defines helper function for all states that the flags field of a segment descriptor can - * have. - */ - struct type_field - { - /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. - */ - enum bitset : uint8_t - { - ACCESSED = - 1U - << 0U, ///< Whether the segment has been accessed since the last time the operating system has cleared the - ///< flag. If enabled it has been accessed, otherwise it has not been accessed since the last clear. - WRITABLE = 1U << 1U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows - ///< read and write access, otherwise only read access is possible. - READABLE = 1U << 1U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows - ///< read and execute access, otherwise only executable access is possible. - CONFORMING = - 1U << 2U, ///< Indicates if the code is allowed to be executed by different access levels - ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise - ///< access from different privilege levels with throw a General-Protectione exception. - EXPAND_DOWN = 1U << 2U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the - ///< data segment expands downwards, otherwise it expands upwards. - CODE_SEGMENT = 1U << 3U, ///< Further defines the actual type of the segment. If enabled this segment is a code - ///< segment, otherwise its a data segment. - LOCAL_DESCRIPTOR_TABLE = 2, ///< The actual type of sytem segment is a local descriptor table. - TASK_STATE_SEGMENT_AVAILABLE = - 9, ///< The actual type of sytem segment is a task state segment that is still available. - TASK_STATE_SEGMENT_BUSY = 11, ///< The actual type of sytem segment is a task state segment that is currently in - ///< use and therefore busy. - CALL_GATE = 11, ///< The actual type of sytem segment is a call gate. - INTERRUPT_GATE = 14, ///< The actual type of sytem segment is a interrupt gate. - TRAP_GATE = 15 ///< The actual type of sytem segment is a trap gate. - }; - - /** - * @brief Default Constructor. - */ - type_field() = default; - - /** - * @brief Constructor. - * - * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to - * allow reading the state of single bits more easily. - */ - type_field(uint8_t flags); - - /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. - * - * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng - * std::bitset. Any additional bits that are set are not relevant. - * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. - */ - auto contains_flags(std::bitset<4U> other) const -> bool; - - /** - * @brief Allows to compare the underlying std::bitset of two instances. - * - * @param other Other instance that we want to compare with. - * @return Whether the underlying std::bitset of both types is the same. - */ - auto operator==(type_field const & other) const -> bool = default; - - private: - std::bitset<4U> _flags = {}; ///< Underlying bitset used to read the flags from. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TYPE_FIELD_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp b/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp index 633d460..85e2949 100644 --- a/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp @@ -8,10 +8,19 @@ namespace teachos::arch::kernel::cpu { + + /** + * @brief Returns the value in the GDTR register. + * + * @return Value of GDTR register. + */ + auto store_global_descriptor_table() -> context_switching::descriptor_table::global_descriptor_table_pointer; + /** * @brief Loads the global_descriptor_table_pointer into the global descriptor table register (GDTR). */ - auto load_global_descriptor_table(context_switching::descriptor_table::global_descriptor_table_pointer gdt_pointer) + auto + load_global_descriptor_table(context_switching::descriptor_table::global_descriptor_table_pointer const & gdt_pointer) -> void; } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 7f04042..7ea5517 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -1,8 +1,8 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP #define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_PHYSICAL_FRAME_HPP -#include "arch/shared/container.hpp" -#include "arch/shared/forward_value_iterator.hpp" +#include "arch/stl/container.hpp" +#include "arch/stl/forward_value_iterator.hpp" #include #include @@ -79,7 +79,7 @@ namespace teachos::arch::memory::allocator {}; ///< Index number of the current physical frame, used to distinguish it from other frames. }; - typedef shared::container> frame_container; + typedef stl::container> frame_container; } // namespace teachos::arch::memory::allocator 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 df9e370..da3c8ff 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,7 @@ #include "arch/memory/heap/heap_allocator.hpp" #include "arch/memory/heap/memory_block.hpp" -#include "arch/shared/mutex.hpp" +#include "arch/stl/mutex.hpp" namespace teachos::arch::memory::heap { @@ -114,7 +114,7 @@ namespace teachos::arch::memory::heap std::size_t heap_start; ///< Start of the allocatable heap area. std::size_t heap_end; ///< End of the allocatable heap area. memory_block * first; ///< First free entry in our memory. - shared::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. + stl::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. }; extern linked_list_allocator kernel_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 e8f6b0a..4c7470b 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 @@ -2,8 +2,8 @@ #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP #include "arch/memory/multiboot/info.hpp" -#include "arch/shared/container.hpp" -#include "arch/shared/contiguous_pointer_iterator.hpp" +#include "arch/stl/container.hpp" +#include "arch/stl/contiguous_pointer_iterator.hpp" #include #include @@ -162,7 +162,7 @@ namespace teachos::arch::memory::multiboot ///< contained in the section, to ensure byte alignment is actually 4 byte. }; - typedef shared::container> elf_section_header_container; + typedef stl::container> elf_section_header_container; } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index c28c986..cc8db8c 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -2,8 +2,8 @@ #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP #include "arch/memory/multiboot/info.hpp" -#include "arch/shared/container.hpp" -#include "arch/shared/contiguous_pointer_iterator.hpp" +#include "arch/stl/container.hpp" +#include "arch/stl/contiguous_pointer_iterator.hpp" #include @@ -46,7 +46,7 @@ namespace teachos::arch::memory::multiboot struct memory_area entries; ///< Specific memory regions. }; - typedef shared::container> memory_area_container; + typedef stl::container> memory_area_container; } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index d820e82..d9164a0 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -84,7 +84,7 @@ namespace teachos::arch::memory::paging {}; ///< Index number of the current virtual page, used to distinguish it from other pages. }; - typedef shared::container> page_container; + typedef stl::container> page_container; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/shared/container.hpp b/arch/x86_64/include/arch/shared/container.hpp deleted file mode 100644 index f2fd1dc..0000000 --- a/arch/x86_64/include/arch/shared/container.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP -#define TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP - -#include - -namespace teachos::arch::shared -{ - /** - * @brief Minimal iterator concept required for usage in container - */ - template - concept Iterator = std::forward_iterator; - - /** - * @brief Read-only container for given template type, that allow to easily use this container instance in C++20 - * ranges calls. - * - * @tparam T Iterator the container uses to signal the start and end of it's data, has to atleast be a simple forward - * iterator. - */ - template - struct container - { - using iterator = T; ///< Iterators used by this container. - using size_type = std::size_t; ///< Maximum size of this container. - - /** - * @brief Defaulted constructor. - */ - container() = default; - - /** - * @brief Constructor. - * - * @param begin Iterator containing non-owning pointer to the first element of all memory areas. - * @param end Iterator pointing to one past the last element of all memory areas. - */ - container(iterator begin, iterator end) - : begin_itr(begin) - , end_itr(end) - { - // Nothing to do - } - - /** - * @brief Returns the iterator pointing to the first element of the memory area. - * Allows using this class in the for each loop, because it follows the InputIterator template scheme. - * - * @return Iterator pointing to first element of the memory area. - */ - auto begin() const -> iterator { return begin_itr; } - - /** - * @brief Returns the iterator pointing to one past the last element of the memory area. - * Allows using this class in the for each loop, because it follows the InputIterator template scheme. - * - * @return Iterator pointing to one past the last element of the memory area. - */ - auto end() const -> iterator { return end_itr; } - - /** - * @brief Calculates the size of this container, simply subtracts the iterator pointing to the first element by the - * last. - * - * @return Actual size of this container. - */ - auto size() const -> size_type { return std::distance(begin(), end()); } - - /** - * @brief Calcualtes the size and returns true if the size is 0 and the container therefore emtpy. - * - * @return Whether the container is empty, size being 0 or not - */ - auto empty() const -> bool { return size() == 0; } - - private: - iterator begin_itr = {}; ///< Pointer to the first element of the given template type. - iterator end_itr = {}; ///< Pointer to one pas the last element of the given template type. - }; - -} // namespace teachos::arch::shared - -#endif // TEACHOS_ARCH_X86_64_SHARED_CONTAINER_HPP diff --git a/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp b/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp deleted file mode 100644 index e2520dc..0000000 --- a/arch/x86_64/include/arch/shared/contiguous_pointer_iterator.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_SHARED_CONTIGUOUS_POINTER_ITERATOR_HPP -#define TEACHOS_ARCH_X86_64_SHARED_CONTIGUOUS_POINTER_ITERATOR_HPP - -#include - -namespace teachos::arch::shared -{ - /** - * @brief Generic contiguous iterator for given template type. Allows to easily use this iterator instance in - * algorithm calls. - * - * @note Allows any value that is contained in an array in memory, which is a block of contiguous memory. This is the - * case because we assume we can simply increment or decrement the pointer address to get the next valid instance of - * the given value type. - * - * @tparam T Value the iterator points too. - */ - template - struct contiguous_pointer_iterator - { - using iterator_category = std::contiguous_iterator_tag; ///< Iterator category of this type. - using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. - using value_type = T; ///< Underlying value pointed to by this iterator. - using reference_type = value_type &; ///< Reference to value returned by dereference * operation. - using pointer_type = value_type *; ///< Pointer to value returned by arrow -> operation. - - /** - * @brief Defaulted constructor. - */ - contiguous_pointer_iterator() = default; - - /** - * @brief Constructor. - * - * @param p Underlying address the iterator should point too. - */ - explicit contiguous_pointer_iterator(value_type * p) - : ptr(p) - { - // Nothing to do - } - - /** - * @brief Dereferences the initally given pointer to its value. - * - * @return Reference to the value. - */ - auto operator*() const -> reference_type { return *ptr; } - - /** - * @brief Get underlying value, which is the intially passed pointer. - * - * @return Pointer to the underlying value passed intially. - */ - auto operator->() const -> pointer_type { return ptr; } - - /** - * @brief Pre decrement operator. Returns a reference to the changed address. - * - * @return Reference to the decremented underlying address. - */ - auto operator--() -> contiguous_pointer_iterator & - { - contiguous_pointer_iterator const old_value = *this; - ++ptr; - return old_value; - } - - /** - * @brief Pre increment operator. Returns a reference to the changed address. - * - * @return Reference to the incremented underlying address. - */ - auto operator++() -> contiguous_pointer_iterator & - { - ++ptr; - return *this; - } - - /** - * @brief Post decrement operator. Returns a copy of the address. - * - * @return Copy of the decremented underlying address. - */ - auto operator--(int) -> contiguous_pointer_iterator - { - auto const old_value = *this; - --ptr; - return old_value; - } - - /** - * @brief Post increment operator. Returns a copy of the address. - * - * @return Copy of the incremented underlying address. - */ - auto operator++(int) -> contiguous_pointer_iterator - { - auto const old_value = *this; - ++ptr; - return old_value; - } - - /** - * @brief Addition assignment operator. Returns a reference to the changed address. - * - * @param value Value we want to add to the underlying address. - * @return Reference to the changed underlying address. - */ - auto operator+=(difference_type value) -> contiguous_pointer_iterator & - { - ptr += value; - return *this; - } - - /** - * @brief Subtraction assignment operator. Returns a reference to the changed address. - * - * @param value Value we want to subtract from the underlying address. - * @return Reference to the changed underlying address. - */ - auto operator-=(difference_type value) -> contiguous_pointer_iterator & - { - ptr -= value; - return *this; - } - - /** - * @brief Addition operator. Returns the changed address. - * - * @param value Value we want to add to a copy of the underlying address. - * @return Copy of underlying address incremented by the given value. - */ - auto operator+(difference_type value) const -> contiguous_pointer_iterator - { - return contiguous_pointer_iterator{ptr + value}; - } - - /** - * @brief Subtraction operator. Returns the changed address. - * - * @param value Value we want to subtrcat from a copy of the underlying address. - * @return Copy of underlying address decremented by the given value. - */ - auto operator-(difference_type value) const -> contiguous_pointer_iterator - { - return contiguous_pointer_iterator{ptr - value}; - } - - /** - * @brief Subtraction operator. Returns the size difference between two iterators. - * - * @param other Other iterator we want to substract the underlying address with ours. - * @return Size difference between the underlying address of this instance and the given iterator. - */ - auto operator-(const contiguous_pointer_iterator & other) const -> difference_type { return ptr - other.ptr; } - - /** - * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the - * dereferenced underlying pointer incremented by the given index. - * - * @param index Index we want to access and get the value from. - * @return Reference to the value at the given index. - */ - auto operator[](difference_type index) const -> value_type & { return *(ptr + index); } - - /** - * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether both iterators point to the same underlying address in memory. - */ - auto operator==(contiguous_pointer_iterator const & other) const -> bool = default; - - /** - * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether the given iterator is smaller or larger than this iterator. - */ - auto operator<=>(contiguous_pointer_iterator const & other) const -> std::strong_ordering = default; - - private: - pointer_type ptr = - {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. - }; - -} // namespace teachos::arch::shared - -#endif // TEACHOS_ARCH_X86_64_SHARED_CONTIGUOUS_POINTER_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/shared/forward_value_iterator.hpp b/arch/x86_64/include/arch/shared/forward_value_iterator.hpp deleted file mode 100644 index c5dfc06..0000000 --- a/arch/x86_64/include/arch/shared/forward_value_iterator.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_SHARED_FORWARD_VALUE_ITERATOR_HPP -#define TEACHOS_ARCH_X86_64_SHARED_FORWARD_VALUE_ITERATOR_HPP - -#include - -namespace teachos::arch::shared -{ - /** - * @brief Concept for a type to have a post and prefix increment operator, that returns the correct type. - */ - template - concept Incrementable = requires(T t) { - { ++t } -> std::same_as; - { t++ } -> std::same_as; - }; - - /** - * @brief Iterable concept for the forward value iterator, meaning the type itself is incrementable and comparable. - */ - template - concept Iterable = std::regular && Incrementable; - - /** - * @brief Generic forward iterator for given template type. Allows to easily use this iterator - * instance in algorithm calls. - * - * @note Allows any value that itself can be incremented until we have reached the end, does not interact with the - * address of the value in any way. - * - * @tparam T Value the iterator contains. - */ - template - struct forward_value_iterator - { - using iterator_category = std::forward_iterator_tag; ///< Iterator category of this type. - using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. - using value_type = T; ///< Underlying value contained by this iterator. - using const_reference_type = - value_type const &; ///< Constant reference to value returned by dereference * operation. - using const_pointer_type = value_type const *; ///< Constant pointer to value returned by arrow -> operation. - - /** - * @brief Defaulted constructor. - */ - forward_value_iterator() = default; - - /** - * @brief Constructor. - * - * @param value Underlying value the iterator contains. - */ - explicit forward_value_iterator(value_type value) - : value(value) - { - // Nothing to do - } - - /** - * @brief Returns the initally given value. - * - * @return Reference to the value. - */ - auto operator*() const -> const_reference_type { return value; } - - /** - * @brief Gets pointer to the underlying value passed intially. - * - * @return Pointer to the underlying value passed intially. - */ - auto operator->() const -> const_pointer_type { return &value; } - - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @return Reference to the incremented underlying value. - */ - auto operator++() -> forward_value_iterator & - { - ++value; - return *this; - } - - /** - * @brief Post increment operator. Returns a copy of the value. - * - * @return Copy of the incremented underlying value. - */ - auto operator++(int) -> forward_value_iterator - { - auto const old_value = *this; - ++value; - return old_value; - } - - /** - * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. - * - * @param other Other iterator to compare to. - * @return Whether both iterators point to the same underlying address in memory. - */ - auto operator==(forward_value_iterator const & other) const -> bool = default; - - private: - value_type value = - {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. - }; - -} // namespace teachos::arch::shared - -#endif // TEACHOS_ARCH_X86_64_SHARED_FORWARD_VALUE_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/shared/mutex.hpp b/arch/x86_64/include/arch/shared/mutex.hpp deleted file mode 100644 index b18a8b3..0000000 --- a/arch/x86_64/include/arch/shared/mutex.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_SHARED_MUTEX_HPP -#define TEACHOS_ARCH_X86_64_SHARED_MUTEX_HPP - -#include - -namespace teachos::arch::shared -{ - /** - * @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). - */ - auto lock() -> void; - - /** - * @brief Try to lock the mutex (non-blocking). - * - * @return True if lock has been acquired and false otherwise. - */ - auto try_lock() -> bool; - - /** - * @brief Unlock the mutex. - */ - auto unlock() -> void; - - private: - std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. - }; - -} // namespace teachos::arch::shared - -#endif // TEACHOS_ARCH_X86_64_SHARED_MUTEX_HPP diff --git a/arch/x86_64/include/arch/stl/container.hpp b/arch/x86_64/include/arch/stl/container.hpp new file mode 100644 index 0000000..b0f513b --- /dev/null +++ b/arch/x86_64/include/arch/stl/container.hpp @@ -0,0 +1,83 @@ +#ifndef TEACHOS_ARCH_X86_64_STL_CONTAINER_HPP +#define TEACHOS_ARCH_X86_64_STL_CONTAINER_HPP + +#include + +namespace teachos::arch::stl +{ + /** + * @brief Minimal iterator concept required for usage in container + */ + template + concept Iterator = std::forward_iterator; + + /** + * @brief Read-only container for given template type, that allow to easily use this container instance in C++20 + * ranges calls. + * + * @tparam T Iterator the container uses to signal the start and end of it's data, has to atleast be a simple forward + * iterator. + */ + template + struct container + { + using iterator = T; ///< Iterators used by this container. + using size_type = std::size_t; ///< Maximum size of this container. + + /** + * @brief Defaulted constructor. + */ + container() = default; + + /** + * @brief Constructor. + * + * @param begin Iterator containing non-owning pointer to the first element of all memory areas. + * @param end Iterator pointing to one past the last element of all memory areas. + */ + container(iterator begin, iterator end) + : begin_itr(begin) + , end_itr(end) + { + // Nothing to do + } + + /** + * @brief Returns the iterator pointing to the first element of the memory area. + * Allows using this class in the for each loop, because it follows the InputIterator template scheme. + * + * @return Iterator pointing to first element of the memory area. + */ + auto begin() const -> iterator { return begin_itr; } + + /** + * @brief Returns the iterator pointing to one past the last element of the memory area. + * Allows using this class in the for each loop, because it follows the InputIterator template scheme. + * + * @return Iterator pointing to one past the last element of the memory area. + */ + auto end() const -> iterator { return end_itr; } + + /** + * @brief Calculates the size of this container, simply subtracts the iterator pointing to the first element by the + * last. + * + * @return Actual size of this container. + */ + auto size() const -> size_type { return std::distance(begin(), end()); } + + /** + * @brief Calcualtes the size and returns true if the size is 0 and the container therefore emtpy. + * + * @return Whether the container is empty, size being 0 or not + */ + auto empty() const -> bool { return size() == 0; } + + private: + iterator begin_itr = {}; ///< Pointer to the first element of the given template type. + iterator end_itr = {}; ///< Pointer to one pas the last element of the given template type. + }; + +} // namespace teachos::arch::stl + +#endif // TEACHOS_ARCH_X86_64_STL_CONTAINER_HPP diff --git a/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp b/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp new file mode 100644 index 0000000..d15d2e2 --- /dev/null +++ b/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp @@ -0,0 +1,190 @@ +#ifndef TEACHOS_ARCH_X86_64_STL_CONTIGUOUS_POINTER_ITERATOR_HPP +#define TEACHOS_ARCH_X86_64_STL_CONTIGUOUS_POINTER_ITERATOR_HPP + +#include + +namespace teachos::arch::stl +{ + /** + * @brief Generic contiguous iterator for given template type. Allows to easily use this iterator instance in + * algorithm calls. + * + * @note Allows any value that is contained in an array in memory, which is a block of contiguous memory. This is the + * case because we assume we can simply increment or decrement the pointer address to get the next valid instance of + * the given value type. + * + * @tparam T Value the iterator points too. + */ + template + struct contiguous_pointer_iterator + { + using iterator_category = std::contiguous_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = T; ///< Underlying value pointed to by this iterator. + using reference_type = value_type &; ///< Reference to value returned by dereference * operation. + using pointer_type = value_type *; ///< Pointer to value returned by arrow -> operation. + + /** + * @brief Defaulted constructor. + */ + contiguous_pointer_iterator() = default; + + /** + * @brief Constructor. + * + * @param p Underlying address the iterator should point too. + */ + explicit contiguous_pointer_iterator(value_type * p) + : ptr(p) + { + // Nothing to do + } + + /** + * @brief Dereferences the initally given pointer to its value. + * + * @return Reference to the value. + */ + auto operator*() const -> reference_type { return *ptr; } + + /** + * @brief Get underlying value, which is the intially passed pointer. + * + * @return Pointer to the underlying value passed intially. + */ + auto operator->() const -> pointer_type { return ptr; } + + /** + * @brief Pre decrement operator. Returns a reference to the changed address. + * + * @return Reference to the decremented underlying address. + */ + auto operator--() -> contiguous_pointer_iterator & + { + contiguous_pointer_iterator const old_value = *this; + ++ptr; + return old_value; + } + + /** + * @brief Pre increment operator. Returns a reference to the changed address. + * + * @return Reference to the incremented underlying address. + */ + auto operator++() -> contiguous_pointer_iterator & + { + ++ptr; + return *this; + } + + /** + * @brief Post decrement operator. Returns a copy of the address. + * + * @return Copy of the decremented underlying address. + */ + auto operator--(int) -> contiguous_pointer_iterator + { + auto const old_value = *this; + --ptr; + return old_value; + } + + /** + * @brief Post increment operator. Returns a copy of the address. + * + * @return Copy of the incremented underlying address. + */ + auto operator++(int) -> contiguous_pointer_iterator + { + auto const old_value = *this; + ++ptr; + return old_value; + } + + /** + * @brief Addition assignment operator. Returns a reference to the changed address. + * + * @param value Value we want to add to the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator+=(difference_type value) -> contiguous_pointer_iterator & + { + ptr += value; + return *this; + } + + /** + * @brief Subtraction assignment operator. Returns a reference to the changed address. + * + * @param value Value we want to subtract from the underlying address. + * @return Reference to the changed underlying address. + */ + auto operator-=(difference_type value) -> contiguous_pointer_iterator & + { + ptr -= value; + return *this; + } + + /** + * @brief Addition operator. Returns the changed address. + * + * @param value Value we want to add to a copy of the underlying address. + * @return Copy of underlying address incremented by the given value. + */ + auto operator+(difference_type value) const -> contiguous_pointer_iterator + { + return contiguous_pointer_iterator{ptr + value}; + } + + /** + * @brief Subtraction operator. Returns the changed address. + * + * @param value Value we want to subtrcat from a copy of the underlying address. + * @return Copy of underlying address decremented by the given value. + */ + auto operator-(difference_type value) const -> contiguous_pointer_iterator + { + return contiguous_pointer_iterator{ptr - value}; + } + + /** + * @brief Subtraction operator. Returns the size difference between two iterators. + * + * @param other Other iterator we want to substract the underlying address with ours. + * @return Size difference between the underlying address of this instance and the given iterator. + */ + auto operator-(const contiguous_pointer_iterator & other) const -> difference_type { return ptr - other.ptr; } + + /** + * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the + * dereferenced underlying pointer incremented by the given index. + * + * @param index Index we want to access and get the value from. + * @return Reference to the value at the given index. + */ + auto operator[](difference_type index) const -> value_type & { return *(ptr + index); } + + /** + * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether both iterators point to the same underlying address in memory. + */ + auto operator==(contiguous_pointer_iterator const & other) const -> bool = default; + + /** + * @brief Defaulted threeway comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether the given iterator is smaller or larger than this iterator. + */ + auto operator<=>(contiguous_pointer_iterator const & other) const -> std::strong_ordering = default; + + private: + pointer_type ptr = + {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. + }; + +} // namespace teachos::arch::stl + +#endif // TEACHOS_ARCH_X86_64_STL_CONTIGUOUS_POINTER_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/stl/forward_value_iterator.hpp b/arch/x86_64/include/arch/stl/forward_value_iterator.hpp new file mode 100644 index 0000000..7c30964 --- /dev/null +++ b/arch/x86_64/include/arch/stl/forward_value_iterator.hpp @@ -0,0 +1,110 @@ +#ifndef TEACHOS_ARCH_X86_64_STL_FORWARD_VALUE_ITERATOR_HPP +#define TEACHOS_ARCH_X86_64_STL_FORWARD_VALUE_ITERATOR_HPP + +#include + +namespace teachos::arch::stl +{ + /** + * @brief Concept for a type to have a post and prefix increment operator, that returns the correct type. + */ + template + concept Incrementable = requires(T t) { + { ++t } -> std::same_as; + { t++ } -> std::same_as; + }; + + /** + * @brief Iterable concept for the forward value iterator, meaning the type itself is incrementable and comparable. + */ + template + concept Iterable = std::regular && Incrementable; + + /** + * @brief Generic forward iterator for given template type. Allows to easily use this iterator + * instance in algorithm calls. + * + * @note Allows any value that itself can be incremented until we have reached the end, does not interact with the + * address of the value in any way. + * + * @tparam T Value the iterator contains. + */ + template + struct forward_value_iterator + { + using iterator_category = std::forward_iterator_tag; ///< Iterator category of this type. + using difference_type = std::ptrdiff_t; ///< Type when diving one instance of this iterator by another. + using value_type = T; ///< Underlying value contained by this iterator. + using const_reference_type = + value_type const &; ///< Constant reference to value returned by dereference * operation. + using const_pointer_type = value_type const *; ///< Constant pointer to value returned by arrow -> operation. + + /** + * @brief Defaulted constructor. + */ + forward_value_iterator() = default; + + /** + * @brief Constructor. + * + * @param value Underlying value the iterator contains. + */ + explicit forward_value_iterator(value_type value) + : value(value) + { + // Nothing to do + } + + /** + * @brief Returns the initally given value. + * + * @return Reference to the value. + */ + auto operator*() const -> const_reference_type { return value; } + + /** + * @brief Gets pointer to the underlying value passed intially. + * + * @return Pointer to the underlying value passed intially. + */ + auto operator->() const -> const_pointer_type { return &value; } + + /** + * @brief Pre increment operator. Returns a reference to the changed value. + * + * @return Reference to the incremented underlying value. + */ + auto operator++() -> forward_value_iterator & + { + ++value; + return *this; + } + + /** + * @brief Post increment operator. Returns a copy of the value. + * + * @return Copy of the incremented underlying value. + */ + auto operator++(int) -> forward_value_iterator + { + auto const old_value = *this; + ++value; + return old_value; + } + + /** + * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. + * + * @param other Other iterator to compare to. + * @return Whether both iterators point to the same underlying address in memory. + */ + auto operator==(forward_value_iterator const & other) const -> bool = default; + + private: + value_type value = + {}; ///< Underlying value the iterator is currently pointing too and should increment or decrement. + }; + +} // namespace teachos::arch::stl + +#endif // TEACHOS_ARCH_X86_64_STL_FORWARD_VALUE_ITERATOR_HPP diff --git a/arch/x86_64/include/arch/stl/mutex.hpp b/arch/x86_64/include/arch/stl/mutex.hpp new file mode 100644 index 0000000..d8fd9dc --- /dev/null +++ b/arch/x86_64/include/arch/stl/mutex.hpp @@ -0,0 +1,57 @@ +#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). + */ + auto lock() -> void; + + /** + * @brief Try to lock the mutex (non-blocking). + * + * @return True if lock has been acquired and false otherwise. + */ + auto try_lock() -> bool; + + /** + * @brief Unlock the mutex. + */ + 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 -- cgit v1.2.3 From e6a9d939ed5e9f89e69efdacc60a1ce6edd1061c Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 15 Mar 2025 12:38:11 +0000 Subject: temporarily make all page table entries user accessible --- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 1de31b5..ef4fe61 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -22,7 +22,7 @@ namespace teachos::arch::memory::paging PRESENT = 1UL << 0UL, ///< Page is in memory and therefore present. ///< is assumed to be READONLY and only that flag is shown in the objdump. WRITABLE = 1UL << 1UL, ///< It is possible to write to the page. - USER_ACCESIBLE = 1UL << 2UL, ///< Page can be accessed in user mode instead of only in kernel mode code. + USER_ACCESSIBLE = 1UL << 2UL, ///< Page can be accessed in user mode instead of only in kernel mode code. WRITE_THROUGH_CACHING = 1UL << 3UL, ///< Write to the page go directly to memory instead of the cache. DISABLED_CACHING = 1UL << 4UL, ///< Page uses caching. ACCESSED = 1UL << 5UL, ///< Page is currently in use. -- 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 --- .../arch/context_switching/descriptor_table/segment_descriptor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index 7106771..7454470 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -56,7 +56,7 @@ namespace teachos::arch::context_switching::descriptor_table access_byte _access = {}; ///< Access byte field (40 - 47) gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55) uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) - uint32_t _reserved = {}; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) + uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::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.hpp | 42 ++++++++++++++++++++++ .../descriptor_table/task_state_segment.hpp | 39 ++++++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/gdtr.hpp | 28 +++++++++++++++ arch/x86_64/include/arch/kernel/cpu/lgdt.hpp | 28 --------------- arch/x86_64/include/arch/kernel/cpu/tr.hpp | 26 ++++++++++++++ 5 files changed, 135 insertions(+), 28 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/gdtr.hpp delete mode 100644 arch/x86_64/include/arch/kernel/cpu/lgdt.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/tr.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp index c4d0e30..ab8f1ac 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp @@ -2,12 +2,54 @@ #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP #include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" +#include "arch/context_switching/descriptor_table/task_state_segment.hpp" namespace teachos::arch::context_switching::descriptor_table { + enum class access_level + { + KERNEL, + USER + }; + + /** + * @brief Creates a generic segment_descriptor from the passed arguments. + * + * @param segment_descriptor_type Defines the type of the segment descriptor. + * @param access_level Defines the segment descriptor access level (KERNEL or USER). + * @return Created segment_descriptor. + */ + auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) + -> segment_descriptor; + + /** + * @brief Creates a global_descriptor_table on the heap and fills it with the following segment registers: + * + * - Kernel Code Segment + * - Kernel Data Segment + * - User Code Segment + * - User Data Segment + * + * @return Created global_descriptor_table. + */ auto create_global_descriptor_table() -> global_descriptor_table; + /** + * @brief Creates a task_state_segment segment_descriptor on the heap. + * + * @param tss task_state_segment whose pointer is used in the segment_descriptor + * @return Created segment_descriptor. + */ + auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor; + + /** + * @brief Initializes the global_descriptor_table and task_state_segment by loading them + * in the GDTR and TR registers respectively. + * + * @return Created global_descriptor_table. + */ auto initialize_global_descriptor_table() -> global_descriptor_table; + } // namespace teachos::arch::context_switching::descriptor_table #endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp new file mode 100644 index 0000000..af7ae7c --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp @@ -0,0 +1,39 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP + +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + /** + * @brief 64-bit task state segment + */ + struct [[gnu::packed]] task_state_segment + { + private: + uint16_t io_map_base_address = {}; + + uint16_t reserved_1 = {}; + uint32_t reserved_2 = {}; + uint32_t reserved_3 = {}; + + uint64_t ist7 = {}; + uint64_t ist6 = {}; + uint64_t ist5 = {}; + uint64_t ist4 = {}; + uint64_t ist3 = {}; + uint64_t ist2 = {}; + uint64_t ist1 = {}; + + uint32_t reserved_4 = {}; + uint32_t reserved_5 = {}; + + uint64_t rsp2 = {}; + uint64_t rsp1 = {}; + uint64_t rsp0 = {}; + + uint32_t reserved_6 = {}; + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp b/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp new file mode 100644 index 0000000..f9220b9 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp @@ -0,0 +1,28 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP + +#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" + +#include +#include + +namespace teachos::arch::kernel::cpu +{ + + /** + * @brief Returns the value in the GDTR register. + * + * @return Value of GDTR register. + */ + auto store_global_descriptor_table() -> context_switching::descriptor_table::global_descriptor_table_pointer; + + /** + * @brief Loads the global_descriptor_table_pointer into the global descriptor table register (GDTR). + */ + auto + load_global_descriptor_table(context_switching::descriptor_table::global_descriptor_table_pointer const & gdt_pointer) + -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp b/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp deleted file mode 100644 index 85e2949..0000000 --- a/arch/x86_64/include/arch/kernel/cpu/lgdt.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_LGDT_HPP -#define TEACHOS_ARCH_X86_64_KERNEL_CPU_LGDT_HPP - -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" - -#include -#include - -namespace teachos::arch::kernel::cpu -{ - - /** - * @brief Returns the value in the GDTR register. - * - * @return Value of GDTR register. - */ - auto store_global_descriptor_table() -> context_switching::descriptor_table::global_descriptor_table_pointer; - - /** - * @brief Loads the global_descriptor_table_pointer into the global descriptor table register (GDTR). - */ - auto - load_global_descriptor_table(context_switching::descriptor_table::global_descriptor_table_pointer const & gdt_pointer) - -> void; - -} // namespace teachos::arch::kernel::cpu - -#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_LGDT_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/tr.hpp b/arch/x86_64/include/arch/kernel/cpu/tr.hpp new file mode 100644 index 0000000..5f99472 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/tr.hpp @@ -0,0 +1,26 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP + +#include "arch/context_switching/descriptor_table/task_state_segment.hpp" + +#include +#include + +namespace teachos::arch::kernel::cpu +{ + + /** + * @brief Returns the value in the LTR register. + * + * @return Value of LTR register. + */ + auto store_task_register() -> uint16_t; + + /** + * @brief Loads the tss_pointer into the task register (TR). + */ + auto load_task_register(uint16_t gdt_offset) -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP -- cgit v1.2.3 From 37cb71ca7771a28835e3ed6aa5ed0797c9ba50fa Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 16 Mar 2025 12:50:14 +0000 Subject: add comment --- arch/x86_64/include/arch/kernel/cpu/tr.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/kernel/cpu/tr.hpp b/arch/x86_64/include/arch/kernel/cpu/tr.hpp index 5f99472..562fab7 100644 --- a/arch/x86_64/include/arch/kernel/cpu/tr.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/tr.hpp @@ -17,7 +17,7 @@ namespace teachos::arch::kernel::cpu auto store_task_register() -> uint16_t; /** - * @brief Loads the tss_pointer into the task register (TR). + * @brief Loads the gdt offset to the tss segment descriptor into the task register (TR). */ auto load_task_register(uint16_t gdt_offset) -> void; -- cgit v1.2.3 From 1658665ff3343382bc2af14ea87642aec544a606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 16 Mar 2025 15:20:27 +0000 Subject: Adjust task state segment struct --- .../descriptor_table/task_state_segment.hpp | 35 +++++++++------------- 1 file changed, 14 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp index af7ae7c..c3b0233 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp @@ -11,28 +11,21 @@ namespace teachos::arch::context_switching::descriptor_table struct [[gnu::packed]] task_state_segment { private: - uint16_t io_map_base_address = {}; - - uint16_t reserved_1 = {}; - uint32_t reserved_2 = {}; - uint32_t reserved_3 = {}; - - uint64_t ist7 = {}; - uint64_t ist6 = {}; - uint64_t ist5 = {}; - uint64_t ist4 = {}; - uint64_t ist3 = {}; - uint64_t ist2 = {}; - uint64_t ist1 = {}; - - uint32_t reserved_4 = {}; - uint32_t reserved_5 = {}; - - uint64_t rsp2 = {}; - uint64_t rsp1 = {}; + uint32_t : 32; uint64_t rsp0 = {}; - - uint32_t reserved_6 = {}; + uint64_t rsp1 = {}; + uint64_t rsp2 = {}; + uint64_t : 64; + uint64_t ist1 = {}; + uint64_t ist2 = {}; + uint64_t ist3 = {}; + uint64_t ist4 = {}; + uint64_t ist5 = {}; + uint64_t ist6 = {}; + uint64_t ist7 = {}; + uint64_t : 64; + uint32_t : 32; + uint16_t io_map_base_address = {}; }; } // namespace teachos::arch::context_switching::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/gdt_flags.hpp | 4 +- .../descriptor_table/global_descriptor_table.hpp | 6 +- .../descriptor_table/segment_descriptor.hpp | 8 +++ .../descriptor_table/task_state_segment.hpp | 4 +- arch/x86_64/include/arch/stl/vector.hpp | 73 ++++++++++++++++++---- 5 files changed, 77 insertions(+), 18 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp index 11f5dd4..de41762 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp @@ -70,10 +70,10 @@ namespace teachos::arch::context_switching::descriptor_table auto get_limit() const -> std::bitset<4U>; /** - * @brief Allows to compare the underlying std::bitset of two instances. + * @brief Allows to compare the underlying set bits of two instances. * * @param other Other instance that we want to compare with. - * @return Whether the underlying std::bitset of both types is the same. + * @return Whether the underlying set bits of both types are the same. */ auto operator==(gdt_flags const & other) const -> bool = default; diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp index ab8f1ac..75e1e9d 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp @@ -30,7 +30,7 @@ namespace teachos::arch::context_switching::descriptor_table * - User Code Segment * - User Data Segment * - * @return Created global_descriptor_table. + * @return Copy of the created global_descriptor_table. */ auto create_global_descriptor_table() -> global_descriptor_table; @@ -46,9 +46,9 @@ namespace teachos::arch::context_switching::descriptor_table * @brief Initializes the global_descriptor_table and task_state_segment by loading them * in the GDTR and TR registers respectively. * - * @return Created global_descriptor_table. + * @return Reference to the created global_descriptor_table. */ - auto initialize_global_descriptor_table() -> global_descriptor_table; + auto initialize_global_descriptor_table() -> global_descriptor_table &; } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp index 7454470..8714eb8 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp @@ -49,6 +49,14 @@ namespace teachos::arch::context_switching::descriptor_table */ auto get_segment_type() const -> segment_descriptor_type; + /** + * @brief Allows to compare the underlying bits of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying set bits of both types are the same. + */ + auto operator==(segment_descriptor const & other) const -> bool = default; + private: // The order in private variables starts for the first variable being the rightmost bit. uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp index c3b0233..1e306af 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp @@ -24,9 +24,9 @@ namespace teachos::arch::context_switching::descriptor_table uint64_t ist6 = {}; uint64_t ist7 = {}; uint64_t : 64; - uint32_t : 32; + uint16_t : 16; uint16_t io_map_base_address = {}; }; } // namespace teachos::arch::context_switching::descriptor_table -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index 112af57..f3d41fd 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -162,13 +162,13 @@ namespace teachos::arch::stl */ void push_back(T const & value) { - _data[_size] = value; - _size++; - if (_size == _capacity) { reserve(_capacity * 2); } + + _data[_size] = value; + _size++; } /** @@ -182,13 +182,13 @@ namespace teachos::arch::stl */ void push_back(T && value) { - _data[_size] = std::move(value); - _size++; - if (_size == _capacity) { reserve(_capacity * 2); } + + _data[_size] = std::move(value); + _size++; } /** @@ -206,13 +206,13 @@ namespace teachos::arch::stl template auto emplace_back(Args &&... args) -> T & { - _data[_size] = T{std::forward(args)...}; - auto const index = _size++; - if (_size == _capacity) { reserve(_capacity * 2); } + + _data[_size] = T{std::forward(args)...}; + auto const index = _size++; return _data[index]; } @@ -254,6 +254,30 @@ namespace teachos::arch::stl */ T const * cbegin() const noexcept { return begin(); } + /** + * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element + * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + T * rbegin() noexcept { return _data + _size - 1; } + + /** + * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element + * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + T const * rbegin() const noexcept { return _data + _size - 1; } + + /** + * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element + * of the non-reversed vector. If the vector is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + T const * crbegin() const noexcept { return rbegin(); } + /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a * placeholder, attempting to access it results in undefined behavior. @@ -278,6 +302,33 @@ namespace teachos::arch::stl */ T const * cend() const noexcept { return end(); } + /** + * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It + * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + T * rend() noexcept { return _data + size - 1; } + + /** + * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It + * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + T const * rend() const noexcept { return _data + size - 1; } + + /** + * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It + * corresponds to the element preceding the first element of the non-reversed vector. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + T const * crend() const noexcept { return rbegin(); } + /** * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable @@ -320,7 +371,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T & back() { return *end(); } + T & back() { return *rbegin(); } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -328,7 +379,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T const & back() const { return *end(); } + T const & back() const { return *rbegin(); } /** * @brief Increase the capacity of the vector (the total number of elements that the vector can hold without -- 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 --- .../arch/context_switching/descriptor_table/access_byte.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp index bafce8d..646c2ca 100644 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp @@ -44,15 +44,15 @@ namespace teachos::arch::context_switching::descriptor_table TRAP_GATE = 15, ///< The actual type of sytem segment is a trap gate. CODE_OR_DATA_SEGMENT = 1U << 4U, ///< Defines a system segment (if 0) or a code/data segment (if 1). ACCESS_LEVEL_KERNEL = - 0U << 4U, ///< Highest privileged level used by the kernel to allow for full access of resources. + 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. ACCESS_LEVEL_ADMIN = - 2U << 4U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. ACCESS_LEVEL_PRIVILEGED_USER = - 4U << 4U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_USER = 6U << 4U, ///< Restricts access to only application and their specific memory. - PRESENT = 1U << 3U << 4U, ///< Present bit; Allows an entry to refer to a valid segment. + ACCESS_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory. + PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment. ///< Must be set (1) for any valid segment. }; -- 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 --- arch/x86_64/include/arch/boot/pointers.hpp | 5 +++ .../descriptor_table/gate_descriptor.hpp | 15 ++++++++ .../descriptor_table/initialization.hpp | 23 ++++++++++++ .../interrupt_descriptor_table.hpp | 14 ++++++++ .../interrupt_descriptor_table_pointer.hpp | 42 ++++++++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/idtr.hpp | 27 ++++++++++++++ arch/x86_64/include/arch/kernel/cpu/if.hpp | 14 ++++++++ arch/x86_64/include/arch/kernel/cpu/jmp.hpp | 35 ++++++++++++++++++ 8 files changed, 175 insertions(+) create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp create mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/idtr.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/if.hpp create mode 100644 arch/x86_64/include/arch/kernel/cpu/jmp.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index fe9c657..2a43f22 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -10,6 +10,11 @@ namespace teachos::arch::boot */ extern "C" size_t const multiboot_information_pointer; + /** + * @brief Address pointing to the start of the multiboot information structure. + */ + extern "C" size_t const segment_register_reload_pointer; + } // namespace teachos::arch::boot #endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp new file mode 100644 index 0000000..f410219 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp @@ -0,0 +1,15 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP + +namespace teachos::arch::context_switching::descriptor_table +{ + struct [[gnu::packed]] gate_descriptor + { + /** + * @brief Default Constructor. + */ + gate_descriptor() = default; + }; +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp new file mode 100644 index 0000000..c587000 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp @@ -0,0 +1,23 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP + +#include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" +#include "arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp" + +namespace teachos::arch::context_switching::descriptor_table +{ + /** + * @brief TODO + * + */ + struct descriptor_tables + { + global_descriptor_table & gdt; ///< Reference to the global descriptor table. + interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table. + }; + + auto initialize_descriptor_tables() -> descriptor_tables; + +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp new file mode 100644 index 0000000..c63932d --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp @@ -0,0 +1,14 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP + +namespace teachos::arch::context_switching::descriptor_table +{ + struct interrupt_descriptor_table + { + }; + + auto initialize_interrupt_descriptor_table() -> void; + +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp new file mode 100644 index 0000000..e8935f4 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp @@ -0,0 +1,42 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP + +#include "arch/context_switching/descriptor_table/gate_descriptor.hpp" +#include "arch/stl/vector.hpp" + +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + typedef stl::vector interrupt_descriptor_table; + + /** + * @brief Represents a pointer to the Interrupt Descriptor Table (IDT). + * + * This structure is used to store the base address and length of the IDT. + */ + struct [[gnu::packed]] interrupt_descriptor_table_pointer + { + /** + * @brief Default constructor. + */ + interrupt_descriptor_table_pointer() = default; + + /** + * @brief Constructor. + */ + interrupt_descriptor_table_pointer(uint16_t table_length, interrupt_descriptor_table * address); + + /** + * @brief Defaulted three-way comparsion operator. + */ + auto operator<=>(interrupt_descriptor_table_pointer const & other) const -> std::strong_ordering = default; + + private: + uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. + interrupt_descriptor_table address = {}; ///< Non-owning pointer to the IDT base address. + }; + +} // namespace teachos::arch::context_switching::descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/idtr.hpp b/arch/x86_64/include/arch/kernel/cpu/idtr.hpp new file mode 100644 index 0000000..724fbdf --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/idtr.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP + +#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" + +#include +#include + +namespace teachos::arch::kernel::cpu +{ + + /** + * @brief Returns the value in the IDTR register. + * + * @return Value of IDTR register. + */ + auto store_interrupt_descriptor_table() -> context_switching::descriptor_table::interrupt_descriptor_table_pointer; + + /** + * @brief Loads the interrupt_descriptor_table_pointer into the interrupt descriptor table register (IDTR). + */ + auto load_interrupt_descriptor_table( + context_switching::descriptor_table::interrupt_descriptor_table_pointer const & idt_pointer) -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/if.hpp b/arch/x86_64/include/arch/kernel/cpu/if.hpp new file mode 100644 index 0000000..51f5d9a --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/if.hpp @@ -0,0 +1,14 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP + +namespace teachos::arch::kernel::cpu +{ + /** + * @brief Sets the interrupt flag (IF) in the EFLAGS register. + * This allows the processor to respond to maskable hardware interrupts. + */ + auto set_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 new file mode 100644 index 0000000..666174c --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp @@ -0,0 +1,35 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP + +#include + +namespace teachos::arch::kernel::cpu +{ + /** + * @brief Far jump - A jump to an instruction located in a different segment. + */ + 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. + }; + + /** + * @brief Near jump - A jump to an instruction within the current code segment. + * + * @param address to jump to. + */ + auto jmp(uint64_t address) -> void; + + /** + * @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. + */ + auto jmp(uint64_t segment, uint64_t offset) -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP -- cgit v1.2.3 From ccb47845d99e098c183f596cd1a3eb1db5c676da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 25 Mar 2025 12:04:43 +0000 Subject: Adjust file structure and fix compilation issues --- .../descriptor_table/access_byte.hpp | 97 ---------------------- .../descriptor_table/gate_descriptor.hpp | 15 ---- .../descriptor_table/gdt_flags.hpp | 86 ------------------- .../descriptor_table/global_descriptor_table.hpp | 55 ------------ .../global_descriptor_table_pointer.hpp | 42 ---------- .../descriptor_table/initialization.hpp | 23 ----- .../interrupt_descriptor_table.hpp | 14 ---- .../interrupt_descriptor_table_pointer.hpp | 42 ---------- .../descriptor_table/segment_descriptor.hpp | 71 ---------------- .../descriptor_table/segment_descriptor_type.hpp | 27 ------ .../descriptor_table/task_state_segment.hpp | 32 ------- .../interrupt_descriptor_table/gate_descriptor.hpp | 15 ++++ .../interrupt_descriptor_table.hpp | 14 ++++ .../interrupt_descriptor_table_pointer.hpp | 42 ++++++++++ .../x86_64/include/arch/context_switching/main.hpp | 23 +++++ .../segment_descriptor_table/access_byte.hpp | 97 ++++++++++++++++++++++ .../segment_descriptor_table/gdt_flags.hpp | 86 +++++++++++++++++++ .../global_descriptor_table.hpp | 55 ++++++++++++ .../global_descriptor_table_pointer.hpp | 42 ++++++++++ .../segment_descriptor.hpp | 71 ++++++++++++++++ .../segment_descriptor_type.hpp | 27 ++++++ .../task_state_segment.hpp | 32 +++++++ arch/x86_64/include/arch/kernel/cpu/gdtr.hpp | 9 +- arch/x86_64/include/arch/kernel/cpu/idtr.hpp | 8 +- arch/x86_64/include/arch/kernel/cpu/tr.hpp | 2 - 25 files changed, 512 insertions(+), 515 deletions(-) delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp delete mode 100644 arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp create mode 100644 arch/x86_64/include/arch/context_switching/main.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp deleted file mode 100644 index 646c2ca..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/access_byte.hpp +++ /dev/null @@ -1,97 +0,0 @@ - -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP - -#include -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - /** - * @brief Defines helper function for all states that the access byte field of a segment descriptor can - * have. - */ - struct [[gnu::packed]] access_byte - { - /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. - */ - enum bitset : uint8_t - { - ACCESSED = - 1U - << 0U, ///< Whether the segment has been accessed since the last time the operating system has cleared the - ///< flag. If enabled it has been accessed, otherwise it has not been accessed since the last clear. - WRITABLE = 1U << 1U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows - ///< read and write access, otherwise only read access is possible. - READABLE = 1U << 1U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows - ///< read and execute access, otherwise only executable access is possible. - CONFORMING = - 1U << 2U, ///< Indicates if the code is allowed to be executed by different access levels - ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise - ///< access from different privilege levels with throw a General-Protectione exception. - EXPAND_DOWN = 1U << 2U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the - ///< data segment expands downwards, otherwise it expands upwards. - CODE_SEGMENT = 1U << 3U, ///< Further defines the actual type of the segment. If enabled this segment is a code - ///< segment, otherwise its a data segment. - LOCAL_DESCRIPTOR_TABLE = 2, ///< The actual type of sytem segment is a local descriptor table. - TASK_STATE_SEGMENT_AVAILABLE = - 9, ///< The actual type of sytem segment is a task state segment that is still available. - TASK_STATE_SEGMENT_BUSY = 11, ///< The actual type of sytem segment is a task state segment that is currently in - ///< use and therefore busy. - CALL_GATE = 11, ///< The actual type of sytem segment is a call gate. - INTERRUPT_GATE = 14, ///< The actual type of sytem segment is a interrupt gate. - TRAP_GATE = 15, ///< The actual type of sytem segment is a trap gate. - CODE_OR_DATA_SEGMENT = 1U << 4U, ///< Defines a system segment (if 0) or a code/data segment (if 1). - ACCESS_LEVEL_KERNEL = - 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. - ACCESS_LEVEL_ADMIN = - 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more - ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_PRIVILEGED_USER = - 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more - ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory. - PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment. - ///< Must be set (1) for any valid segment. - }; - - /** - * @brief Default Constructor. - */ - access_byte() = default; - - /** - * @brief Constructor. - * - * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used - * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags - * are enabled or not using contains_flags method. - */ - access_byte(uint8_t flags); - - /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. - * - * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng - * std::bitset. Any additional bits that are set are not relevant. - * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. - */ - auto contains_flags(std::bitset<8U> other) const -> bool; - - /** - * @brief Allows to compare the underlying std::bitset of two instances. - * - * @param other Other instance that we want to compare with. - * @return Whether the underlying std::bitset of both types is the same. - */ - auto operator==(access_byte const & other) const -> bool = default; - - private: - uint8_t _flags = {}; ///< Underlying bitset used to read the flags from. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp deleted file mode 100644 index f410219..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gate_descriptor.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP - -namespace teachos::arch::context_switching::descriptor_table -{ - struct [[gnu::packed]] gate_descriptor - { - /** - * @brief Default Constructor. - */ - gate_descriptor() = default; - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp deleted file mode 100644 index de41762..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/gdt_flags.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP - -#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - /** - * @brief Defines helper function for all states that the flags field of a segment descriptor can - * have. - */ - struct [[gnu::packed]] gdt_flags - { - /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. - */ - enum bitset : uint8_t - { - LENGTH = 1U << 0U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment - ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions are - ///< executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. If bis - ///< is set the DEFAULT_LENGTH bis needs to be 0 - UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 - ///< GiB, 4 KiB otherwise. - STACK_POINTER_SIZE = 1U << 1U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for - ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. - DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and - ///< operands. Enable for 32 bit, 16 bit otherwise. - GRANULARITY = 1U << 2U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte - ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. - }; - - /** - * @brief Default Constructor. - */ - gdt_flags() = default; - - /** - * @brief Constructor. - * - * @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. This value is saved and can later be used to check whether certain flags are - * enabled or not using contains_flags method. - * @param limit Does not necessarily make sense in the gdt flags type, but because the flags alone are only 4 bit - * the type would still require the space for a complete bit. Therefore the 4 bit segment limit field before the - * flags field is included in this type to ensure we actually contain 8 bit of data. - */ - gdt_flags(uint8_t flags, std::bitset<20U> limit); - - /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. - * - * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng - * std::bitset. Any additional bits that are set are not relevant. - * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. - */ - auto contains_flags(std::bitset<4U> other) const -> bool; - - /** - * @brief Get part of the segment limit that is saved in the gdt flags. This does not necessarily make sense in this - * object, but it has to be included here because a struct can not be smaller than a full byte. Therefore we include - * the 4 bit segment limit field so that it results in a compelte byte with the addtional 4 bit of gdt flags. - * - * @return 4-bit limit segment - */ - auto get_limit() const -> std::bitset<4U>; - - /** - * @brief Allows to compare the underlying set bits of two instances. - * - * @param other Other instance that we want to compare with. - * @return Whether the underlying set bits of both types are the same. - */ - auto operator==(gdt_flags const & other) const -> bool = default; - - private: - uint8_t _limit_2 : 4 = {}; - uint8_t _flags : 4 = {}; ///< Underlying bitset used to read the flags from. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GDT_FLAGS_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp deleted file mode 100644 index 75e1e9d..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP - -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" -#include "arch/context_switching/descriptor_table/task_state_segment.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - enum class access_level - { - KERNEL, - USER - }; - - /** - * @brief Creates a generic segment_descriptor from the passed arguments. - * - * @param segment_descriptor_type Defines the type of the segment descriptor. - * @param access_level Defines the segment descriptor access level (KERNEL or USER). - * @return Created segment_descriptor. - */ - auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) - -> segment_descriptor; - - /** - * @brief Creates a global_descriptor_table on the heap and fills it with the following segment registers: - * - * - Kernel Code Segment - * - Kernel Data Segment - * - User Code Segment - * - User Data Segment - * - * @return Copy of the created global_descriptor_table. - */ - auto create_global_descriptor_table() -> global_descriptor_table; - - /** - * @brief Creates a task_state_segment segment_descriptor on the heap. - * - * @param tss task_state_segment whose pointer is used in the segment_descriptor - * @return Created segment_descriptor. - */ - auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor; - - /** - * @brief Initializes the global_descriptor_table and task_state_segment by loading them - * in the GDTR and TR registers respectively. - * - * @return Reference to the created global_descriptor_table. - */ - auto initialize_global_descriptor_table() -> global_descriptor_table &; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp deleted file mode 100644 index ed17be3..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP - -#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" -#include "arch/stl/vector.hpp" - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - typedef stl::vector global_descriptor_table; - - /** - * @brief Represents a pointer to the Global Descriptor Table (GDT). - * - * This structure is used to store the base address and length of the GDT. - * It is used when loading or modifying the GDT during context switching. - */ - struct [[gnu::packed]] global_descriptor_table_pointer - { - /** - * @brief Default constructor. - */ - global_descriptor_table_pointer() = default; - - /** - * @brief Constructor. - */ - global_descriptor_table_pointer(uint16_t table_length, global_descriptor_table * address); - - /** - * @brief Defaulted three-way comparsion operator. - */ - auto operator<=>(global_descriptor_table_pointer const & other) const -> std::strong_ordering = default; - - private: - uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. - global_descriptor_table * address = {}; ///< Non-owning pointer to the GDT base address. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp deleted file mode 100644 index c587000..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/initialization.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP - -#include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" -#include "arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - /** - * @brief TODO - * - */ - struct descriptor_tables - { - global_descriptor_table & gdt; ///< Reference to the global descriptor table. - interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table. - }; - - auto initialize_descriptor_tables() -> descriptor_tables; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp deleted file mode 100644 index c63932d..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP - -namespace teachos::arch::context_switching::descriptor_table -{ - struct interrupt_descriptor_table - { - }; - - auto initialize_interrupt_descriptor_table() -> void; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp deleted file mode 100644 index e8935f4..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/interrupt_descriptor_table_pointer.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP - -#include "arch/context_switching/descriptor_table/gate_descriptor.hpp" -#include "arch/stl/vector.hpp" - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - typedef stl::vector interrupt_descriptor_table; - - /** - * @brief Represents a pointer to the Interrupt Descriptor Table (IDT). - * - * This structure is used to store the base address and length of the IDT. - */ - struct [[gnu::packed]] interrupt_descriptor_table_pointer - { - /** - * @brief Default constructor. - */ - interrupt_descriptor_table_pointer() = default; - - /** - * @brief Constructor. - */ - interrupt_descriptor_table_pointer(uint16_t table_length, interrupt_descriptor_table * address); - - /** - * @brief Defaulted three-way comparsion operator. - */ - auto operator<=>(interrupt_descriptor_table_pointer const & other) const -> std::strong_ordering = default; - - private: - uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. - interrupt_descriptor_table address = {}; ///< Non-owning pointer to the IDT base address. - }; - -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp deleted file mode 100644 index 8714eb8..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP - -#include "arch/context_switching/descriptor_table/access_byte.hpp" -#include "arch/context_switching/descriptor_table/gdt_flags.hpp" -#include "arch/context_switching/descriptor_table/segment_descriptor_type.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - __extension__ typedef __int128 int128_t; - __extension__ typedef unsigned __int128 uint128_t; - - /** - * @brief Defines helper function for all states and the actual data the segment descriptor can have. - */ - struct [[gnu::packed]] segment_descriptor - { - /** - * @brief Default Constructor. - */ - segment_descriptor() = default; - - /** - * @brief Constructor. - * - * @note Created segment descriptor copies the given bytes into theese components ending with a 32 bit reserved - * field that has to be used, because the 64-bit segment descriptor needs to be big enough for two 32-bit segment - * descriptor. - * - 8 bit Access Type - * - 4 bit Flags - * - 64 bit Base Address - * - 20 bit Limit - * - * @param flags Copies the bits set from the given data into the individual components of a segment - * descriptor. - */ - explicit segment_descriptor(uint128_t flags); - - /** - * @brief Constructor. - * - * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of - * a segment descriptor. - */ - segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit); - - /** - * @brief Calculates the underlying segment type that this segement descriptor is describing. - */ - auto get_segment_type() const -> segment_descriptor_type; - - /** - * @brief Allows to compare the underlying bits of two instances. - * - * @param other Other instance that we want to compare with. - * @return Whether the underlying set bits of both types are the same. - */ - auto operator==(segment_descriptor const & other) const -> bool = default; - - private: - // The order in private variables starts for the first variable being the rightmost bit. - uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) - uint32_t _base_1 : 24 = {}; ///< First part of the base field (16 - 39) - access_byte _access = {}; ///< Access byte field (40 - 47) - gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55) - uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) - uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp deleted file mode 100644 index 4815fca..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/segment_descriptor_type.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - /** - * @brief Possible overlying types of the segment descriptor. Allowing to discern between the major types, which - * result in different handling of the actual data contained in the descriptor. - */ - enum class segment_descriptor_type : uint8_t - { - SYSTEM_SEGMENT, ///< The segment is of type system, is distinguished by the Descriptor Type field in the Access - ///< Byte. Can be further distinguised to specific system segment types using the Type Field in the - ///< Access Byte. - DATA_SEGMENT, ///< The segment is of type data, is is distinguished by the Descriptor Type field in the Access - ///< Byte and the first bit of the Type Field in the Access Byte. Can be further distinguised to - ///< specific data segment types using the the remaining bits in the Type Field in the Access Byte. - CODE_SEGMENT, ///< The segment is of type code, is is distinguished by the Descriptor Type field in - ///< the Access Byte and the first bit of the Type Field in the Access Byte. Can be - ///< further distinguised to specific data segment types using the the remaining bits in - ///< the Type Field in the Access Byte. - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP diff --git a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp b/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp deleted file mode 100644 index 1e306af..0000000 --- a/arch/x86_64/include/arch/context_switching/descriptor_table/task_state_segment.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP - -#include - -namespace teachos::arch::context_switching::descriptor_table -{ - /** - * @brief 64-bit task state segment - */ - struct [[gnu::packed]] task_state_segment - { - private: - uint32_t : 32; - uint64_t rsp0 = {}; - uint64_t rsp1 = {}; - uint64_t rsp2 = {}; - uint64_t : 64; - uint64_t ist1 = {}; - uint64_t ist2 = {}; - uint64_t ist3 = {}; - uint64_t ist4 = {}; - uint64_t ist5 = {}; - uint64_t ist6 = {}; - uint64_t ist7 = {}; - uint64_t : 64; - uint16_t : 16; - uint16_t io_map_base_address = {}; - }; -} // namespace teachos::arch::context_switching::descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp new file mode 100644 index 0000000..2252b7b --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp @@ -0,0 +1,15 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + struct [[gnu::packed]] gate_descriptor + { + /** + * @brief Default Constructor. + */ + gate_descriptor() = default; + }; +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp new file mode 100644 index 0000000..ac52a39 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp @@ -0,0 +1,14 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + struct interrupt_descriptor_table + { + }; + + auto initialize_interrupt_descriptor_table() -> void; + +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp new file mode 100644 index 0000000..de40f90 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp @@ -0,0 +1,42 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP + +#include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp" +#include "arch/stl/vector.hpp" + +#include + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + typedef stl::vector interrupt_descriptor_table; + + /** + * @brief Represents a pointer to the Interrupt Descriptor Table (IDT). + * + * This structure is used to store the base address and length of the IDT. + */ + struct [[gnu::packed]] interrupt_descriptor_table_pointer + { + /** + * @brief Default constructor. + */ + interrupt_descriptor_table_pointer() = default; + + /** + * @brief Constructor. + */ + interrupt_descriptor_table_pointer(uint16_t table_length, interrupt_descriptor_table * address); + + /** + * @brief Defaulted three-way comparsion operator. + */ + auto operator<=>(interrupt_descriptor_table_pointer const & other) const -> std::strong_ordering = default; + + private: + uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. + interrupt_descriptor_table * address = {}; ///< Non-owning pointer to the IDT base address. + }; + +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp new file mode 100644 index 0000000..ef642d6 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/main.hpp @@ -0,0 +1,23 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP + +#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp" +#include "arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp" + +namespace teachos::arch::context_switching +{ + /** + * @brief TODO + * + */ + struct descriptor_tables + { + segment_descriptor_table::global_descriptor_table & gdt; ///< Reference to the global descriptor table. + interrupt_descriptor_table::interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table. + }; + + auto initialize_descriptor_tables() -> descriptor_tables; + +} // namespace teachos::arch::context_switching + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp new file mode 100644 index 0000000..bbf3f49 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp @@ -0,0 +1,97 @@ + +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP + +#include +#include + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + /** + * @brief Defines helper function for all states that the access byte field of a segment descriptor can + * have. + */ + struct [[gnu::packed]] access_byte + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + ACCESSED = + 1U + << 0U, ///< Whether the segment has been accessed since the last time the operating system has cleared the + ///< flag. If enabled it has been accessed, otherwise it has not been accessed since the last clear. + WRITABLE = 1U << 1U, ///< Indicates if the data segment is writable or not. If enabled the code segment allows + ///< read and write access, otherwise only read access is possible. + READABLE = 1U << 1U, ///< Indicates if the code segment is readable or not. If enabled the code segment allows + ///< read and execute access, otherwise only executable access is possible. + CONFORMING = + 1U << 2U, ///< Indicates if the code is allowed to be executed by different access levels + ///< (higher or lower) in code segments. If enabled the code segment allows access, otherwise + ///< access from different privilege levels with throw a General-Protectione exception. + EXPAND_DOWN = 1U << 2U, ///< Indicates if the expansion direction is up or down in data segments. If enabled the + ///< data segment expands downwards, otherwise it expands upwards. + CODE_SEGMENT = 1U << 3U, ///< Further defines the actual type of the segment. If enabled this segment is a code + ///< segment, otherwise its a data segment. + LOCAL_DESCRIPTOR_TABLE = 2, ///< The actual type of sytem segment is a local descriptor table. + TASK_STATE_SEGMENT_AVAILABLE = + 9, ///< The actual type of sytem segment is a task state segment that is still available. + TASK_STATE_SEGMENT_BUSY = 11, ///< The actual type of sytem segment is a task state segment that is currently in + ///< use and therefore busy. + CALL_GATE = 11, ///< The actual type of sytem segment is a call gate. + INTERRUPT_GATE = 14, ///< The actual type of sytem segment is a interrupt gate. + TRAP_GATE = 15, ///< The actual type of sytem segment is a trap gate. + CODE_OR_DATA_SEGMENT = 1U << 4U, ///< Defines a system segment (if 0) or a code/data segment (if 1). + ACCESS_LEVEL_KERNEL = + 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. + ACCESS_LEVEL_ADMIN = + 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + ACCESS_LEVEL_PRIVILEGED_USER = + 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + ACCESS_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory. + PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment. + ///< Must be set (1) for any valid segment. + }; + + /** + * @brief Default Constructor. + */ + access_byte() = default; + + /** + * @brief Constructor. + * + * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used + * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags + * are enabled or not using contains_flags method. + */ + access_byte(uint8_t flags); + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + */ + auto contains_flags(std::bitset<8U> other) const -> bool; + + /** + * @brief Allows to compare the underlying std::bitset of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying std::bitset of both types is the same. + */ + auto operator==(access_byte const & other) const -> bool = default; + + private: + uint8_t _flags = {}; ///< Underlying bitset used to read the flags from. + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_ACCESS_BYTE_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp new file mode 100644 index 0000000..2ce5286 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -0,0 +1,86 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GDT_FLAGS_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GDT_FLAGS_HPP + +#include "arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp" + +#include + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + /** + * @brief Defines helper function for all states that the flags field of a segment descriptor can + * have. + */ + struct [[gnu::packed]] gdt_flags + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + LENGTH = 1U << 0U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment + ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions are + ///< executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. If bis + ///< is set the DEFAULT_LENGTH bis needs to be 0 + UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 + ///< GiB, 4 KiB otherwise. + STACK_POINTER_SIZE = 1U << 1U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for + ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. + DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and + ///< operands. Enable for 32 bit, 16 bit otherwise. + GRANULARITY = 1U << 2U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte + ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. + }; + + /** + * @brief Default Constructor. + */ + gdt_flags() = default; + + /** + * @brief Constructor. + * + * @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. This value is saved and can later be used to check whether certain flags are + * enabled or not using contains_flags method. + * @param limit Does not necessarily make sense in the gdt flags type, but because the flags alone are only 4 bit + * the type would still require the space for a complete bit. Therefore the 4 bit segment limit field before the + * flags field is included in this type to ensure we actually contain 8 bit of data. + */ + gdt_flags(uint8_t flags, std::bitset<20U> limit); + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + */ + auto contains_flags(std::bitset<4U> other) const -> bool; + + /** + * @brief Get part of the segment limit that is saved in the gdt flags. This does not necessarily make sense in this + * object, but it has to be included here because a struct can not be smaller than a full byte. Therefore we include + * the 4 bit segment limit field so that it results in a compelte byte with the addtional 4 bit of gdt flags. + * + * @return 4-bit limit segment + */ + auto get_limit() const -> std::bitset<4U>; + + /** + * @brief Allows to compare the underlying set bits of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying set bits of both types are the same. + */ + auto operator==(gdt_flags const & other) const -> bool = default; + + private: + uint8_t _limit_2 : 4 = {}; + uint8_t _flags : 4 = {}; ///< Underlying bitset used to read the flags from. + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GDT_FLAGS_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp new file mode 100644 index 0000000..a111a1f --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp @@ -0,0 +1,55 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP + +#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp" +#include "arch/context_switching/segment_descriptor_table/task_state_segment.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + enum class access_level + { + KERNEL, + USER + }; + + /** + * @brief Creates a generic segment_descriptor from the passed arguments. + * + * @param segment_descriptor_type Defines the type of the segment descriptor. + * @param access_level Defines the segment descriptor access level (KERNEL or USER). + * @return Created segment_descriptor. + */ + auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) + -> segment_descriptor; + + /** + * @brief Creates a global_descriptor_table on the heap and fills it with the following segment registers: + * + * - Kernel Code Segment + * - Kernel Data Segment + * - User Code Segment + * - User Data Segment + * + * @return Copy of the created global_descriptor_table. + */ + auto create_global_descriptor_table() -> global_descriptor_table; + + /** + * @brief Creates a task_state_segment segment_descriptor on the heap. + * + * @param tss task_state_segment whose pointer is used in the segment_descriptor + * @return Created segment_descriptor. + */ + auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor; + + /** + * @brief Initializes the global_descriptor_table and task_state_segment by loading them + * in the GDTR and TR registers respectively. + * + * @return Reference to the created global_descriptor_table. + */ + auto initialize_global_descriptor_table() -> global_descriptor_table &; + +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp new file mode 100644 index 0000000..b66070b --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp @@ -0,0 +1,42 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP + +#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" +#include "arch/stl/vector.hpp" + +#include + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + typedef stl::vector global_descriptor_table; + + /** + * @brief Represents a pointer to the Global Descriptor Table (GDT). + * + * This structure is used to store the base address and length of the GDT. + * It is used when loading or modifying the GDT during context switching. + */ + struct [[gnu::packed]] global_descriptor_table_pointer + { + /** + * @brief Default constructor. + */ + global_descriptor_table_pointer() = default; + + /** + * @brief Constructor. + */ + global_descriptor_table_pointer(uint16_t table_length, global_descriptor_table * address); + + /** + * @brief Defaulted three-way comparsion operator. + */ + auto operator<=>(global_descriptor_table_pointer const & other) const -> std::strong_ordering = default; + + private: + uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. + global_descriptor_table * address = {}; ///< Non-owning pointer to the GDT base address. + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp new file mode 100644 index 0000000..7fe4ecb --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp @@ -0,0 +1,71 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP + +#include "arch/context_switching/segment_descriptor_table/access_byte.hpp" +#include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp" +#include "arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + __extension__ typedef __int128 int128_t; + __extension__ typedef unsigned __int128 uint128_t; + + /** + * @brief Defines helper function for all states and the actual data the segment descriptor can have. + */ + struct [[gnu::packed]] segment_descriptor + { + /** + * @brief Default Constructor. + */ + segment_descriptor() = default; + + /** + * @brief Constructor. + * + * @note Created segment descriptor copies the given bytes into theese components ending with a 32 bit reserved + * field that has to be used, because the 64-bit segment descriptor needs to be big enough for two 32-bit segment + * descriptor. + * - 8 bit Access Type + * - 4 bit Flags + * - 64 bit Base Address + * - 20 bit Limit + * + * @param flags Copies the bits set from the given data into the individual components of a segment + * descriptor. + */ + explicit segment_descriptor(uint128_t flags); + + /** + * @brief Constructor. + * + * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of + * a segment descriptor. + */ + segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit); + + /** + * @brief Calculates the underlying segment type that this segement descriptor is describing. + */ + auto get_segment_type() const -> segment_descriptor_type; + + /** + * @brief Allows to compare the underlying bits of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying set bits of both types are the same. + */ + auto operator==(segment_descriptor const & other) const -> bool = default; + + private: + // The order in private variables starts for the first variable being the rightmost bit. + uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) + uint32_t _base_1 : 24 = {}; ///< First part of the base field (16 - 39) + access_byte _access = {}; ///< Access byte field (40 - 47) + gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55) + uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) + uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp new file mode 100644 index 0000000..8770b81 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP + +#include + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + /** + * @brief Possible overlying types of the segment descriptor. Allowing to discern between the major types, which + * result in different handling of the actual data contained in the descriptor. + */ + enum class segment_descriptor_type : uint8_t + { + SYSTEM_SEGMENT, ///< The segment is of type system, is distinguished by the Descriptor Type field in the Access + ///< Byte. Can be further distinguised to specific system segment types using the Type Field in the + ///< Access Byte. + DATA_SEGMENT, ///< The segment is of type data, is is distinguished by the Descriptor Type field in the Access + ///< Byte and the first bit of the Type Field in the Access Byte. Can be further distinguised to + ///< specific data segment types using the the remaining bits in the Type Field in the Access Byte. + CODE_SEGMENT, ///< The segment is of type code, is is distinguished by the Descriptor Type field in + ///< the Access Byte and the first bit of the Type Field in the Access Byte. Can be + ///< further distinguised to specific data segment types using the the remaining bits in + ///< the Type Field in the Access Byte. + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_TYPES_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp new file mode 100644 index 0000000..d4aa5e8 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/task_state_segment.hpp @@ -0,0 +1,32 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP + +#include + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + /** + * @brief 64-bit task state segment + */ + struct [[gnu::packed]] task_state_segment + { + private: + uint32_t : 32; + uint64_t rsp0 = {}; + uint64_t rsp1 = {}; + uint64_t rsp2 = {}; + uint64_t : 64; + uint64_t ist1 = {}; + uint64_t ist2 = {}; + uint64_t ist3 = {}; + uint64_t ist4 = {}; + uint64_t ist5 = {}; + uint64_t ist6 = {}; + uint64_t ist7 = {}; + uint64_t : 64; + uint16_t : 16; + uint16_t io_map_base_address = {}; + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_TASK_STATE_SEGMENT_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp b/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp index f9220b9..68b950d 100644 --- a/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/gdtr.hpp @@ -1,7 +1,7 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP #define TEACHOS_ARCH_X86_64_KERNEL_CPU_GDTR_HPP -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" +#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp" #include #include @@ -14,14 +14,13 @@ namespace teachos::arch::kernel::cpu * * @return Value of GDTR register. */ - auto store_global_descriptor_table() -> context_switching::descriptor_table::global_descriptor_table_pointer; + auto store_global_descriptor_table() -> context_switching::segment_descriptor_table::global_descriptor_table_pointer; /** * @brief Loads the global_descriptor_table_pointer into the global descriptor table register (GDTR). */ - auto - load_global_descriptor_table(context_switching::descriptor_table::global_descriptor_table_pointer const & gdt_pointer) - -> void; + auto load_global_descriptor_table( + context_switching::segment_descriptor_table::global_descriptor_table_pointer const & gdt_pointer) -> void; } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/include/arch/kernel/cpu/idtr.hpp b/arch/x86_64/include/arch/kernel/cpu/idtr.hpp index 724fbdf..cb800d0 100644 --- a/arch/x86_64/include/arch/kernel/cpu/idtr.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/idtr.hpp @@ -1,26 +1,26 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP #define TEACHOS_ARCH_X86_64_KERNEL_CPU_IDTR_HPP -#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" +#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp" #include #include namespace teachos::arch::kernel::cpu { - /** * @brief Returns the value in the IDTR register. * * @return Value of IDTR register. */ - auto store_interrupt_descriptor_table() -> context_switching::descriptor_table::interrupt_descriptor_table_pointer; + auto store_interrupt_descriptor_table() + -> context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer; /** * @brief Loads the interrupt_descriptor_table_pointer into the interrupt descriptor table register (IDTR). */ auto load_interrupt_descriptor_table( - context_switching::descriptor_table::interrupt_descriptor_table_pointer const & idt_pointer) -> void; + context_switching::interrupt_descriptor_table::interrupt_descriptor_table_pointer const & idt_pointer) -> void; } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/include/arch/kernel/cpu/tr.hpp b/arch/x86_64/include/arch/kernel/cpu/tr.hpp index 562fab7..7c856f1 100644 --- a/arch/x86_64/include/arch/kernel/cpu/tr.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/tr.hpp @@ -1,8 +1,6 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP #define TEACHOS_ARCH_X86_64_KERNEL_CPU_TR_HPP -#include "arch/context_switching/descriptor_table/task_state_segment.hpp" - #include #include -- cgit v1.2.3 From 66fefaeb16bcbc4eae5ce5256ae76f51a155cded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 25 Mar 2025 16:58:24 +0000 Subject: Implement idtr structure and document possible flags. --- .../interrupt_descriptor_table/gate_descriptor.hpp | 54 ++++++++++++++++ .../interrupt_descriptor_table/idt_flags.hpp | 74 ++++++++++++++++++++++ .../interrupt_descriptor_table.hpp | 14 ++-- .../interrupt_descriptor_table_pointer.hpp | 4 +- .../interrupt_descriptor_table/ist_offset.hpp | 41 ++++++++++++ .../segment_selector.hpp | 74 ++++++++++++++++++++++ .../x86_64/include/arch/context_switching/main.hpp | 3 +- .../segment_descriptor_table/access_byte.hpp | 14 ++-- .../segment_descriptor_table/gdt_flags.hpp | 4 +- .../global_descriptor_table.hpp | 36 ----------- .../global_descriptor_table_pointer.hpp | 2 +- arch/x86_64/include/arch/kernel/cpu/ss.hpp | 39 ++---------- .../arch/memory/allocator/physical_frame.hpp | 4 +- .../arch/memory/multiboot/elf_symbols_section.hpp | 2 +- .../include/arch/memory/multiboot/memory_map.hpp | 2 +- .../include/arch/memory/paging/virtual_page.hpp | 4 +- 16 files changed, 275 insertions(+), 96 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp create mode 100644 arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp index 2252b7b..196430f 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp @@ -1,14 +1,68 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP +#include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp" +#include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp" +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" + +#include +#include + namespace teachos::arch::context_switching::interrupt_descriptor_table { + __extension__ typedef __int128 int128_t; + __extension__ typedef unsigned __int128 uint128_t; + + /** + * @brief Defines helper function for all states and the actual data the gate descriptor can have. + */ struct [[gnu::packed]] gate_descriptor { /** * @brief Default Constructor. */ gate_descriptor() = default; + + /** + * @brief Constructor. + * + * @note Created gate descriptor copies the given bytes into these components ending with a 32 bit reserved + * field that has to be used, because the 64-bit gate descriptor needs to be big enough for two 32-bit gate + * descriptor. + * - 16 bit Segment Selector + * - 3 bit IST + * - 8 bit Type and Flags + * - 64 bit Offset + * + * @param flags Copies the bits set from the given data into the individual components of a gate + * descriptor. + */ + explicit gate_descriptor(uint128_t flags); + + /** + * @brief Constructor. + * + * @param selector, ist, flags, offset Copies the bits set from the given data into the individual components of + * a gate descriptor. + */ + gate_descriptor(segment_selector selector, ist_offset ist, idt_flags flags, uint64_t offset); + + /** + * @brief Allows to compare the underlying bits of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying set bits of both types are the same. + */ + auto operator==(gate_descriptor const & other) const -> bool = default; + + private: + // The order in private variables starts for the first variable being the rightmost bit. + uint16_t _offset_1 = {}; ///< First part of the offset field (0 - 15) + segment_selector _selector = {}; ///< Segment selector (16 - 31) + ist_offset _ist = {}; ///< Interrupt Stack Table offset (32 - 39) + idt_flags _flags = {}; ///< Gate Type and Flags (40 - 47) + uint64_t _offset_2 : 48 = {}; ///< Second part of the offset field (48 - 95) + uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp new file mode 100644 index 0000000..f153e36 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp @@ -0,0 +1,74 @@ + +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP + +#include +#include + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + /** + * @brief Defines helper function for all states that the access byte field of a segment descriptor can + * have. + */ + struct [[gnu::packed]] idt_flags + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + INTERRUPT_GATE = 16U, ///< The actual type of gate segment is a interrupt gate. + TRAP_GATE = 17U, ///< The actual type of gate segment is a trap gate. + DESCRIPTOR_LEVEL_KERNEL = + 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. + DESCRIPTOR_LEVEL_ADMIN = + 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + DESCRIPTOR_LEVEL_PRIVILEGED_USER = + 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + DESCRIPTOR_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory. + PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment. + ///< Must be set (1) for any valid segment. + }; + + /** + * @brief Default Constructor. + */ + idt_flags() = default; + + /** + * @brief Constructor. + * + * @param flags Allows to set flags for the access byte field using the unscoped enum contained in this class, used + * to allow for direct integer conversion. This value is saved and can later be used to check whether certain flags + * are enabled or not using contains_flags method. + */ + idt_flags(uint8_t flags); + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + */ + auto contains_flags(std::bitset<8U> other) const -> bool; + + /** + * @brief Allows to compare the underlying std::bitset of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying std::bitset of both types is the same. + */ + auto operator==(idt_flags const & other) const -> bool = default; + + private: + uint8_t _flags = {}; ///< Underlying bits used to read the flags from. + }; +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IDT_FLAGS_HPP \ No newline at end of file diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp index ac52a39..dd55cd7 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp @@ -1,13 +1,17 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP +#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp" + namespace teachos::arch::context_switching::interrupt_descriptor_table { - struct interrupt_descriptor_table - { - }; - - auto initialize_interrupt_descriptor_table() -> void; + /** + * @brief Initializes the interrupt_descriptor_table by loading it + * in the IDTR register. + * + * @return Reference to the created interrupt_descriptor_table. + */ + auto initialize_interrupt_descriptor_table() -> interrupt_descriptor_table &; } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp index de40f90..d853ff0 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp @@ -4,11 +4,9 @@ #include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp" #include "arch/stl/vector.hpp" -#include - namespace teachos::arch::context_switching::interrupt_descriptor_table { - typedef stl::vector interrupt_descriptor_table; + using interrupt_descriptor_table = stl::vector; /** * @brief Represents a pointer to the Interrupt Descriptor Table (IDT). diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp new file mode 100644 index 0000000..f31a898 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp @@ -0,0 +1,41 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP + +#include +#include + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + /** + * @brief Defines helper function for all states that the ist field of a gate descriptor can + * have. Is automatically increased to one byte in size, to include the following 5 reserved bits in the gate + * descriptor. + */ + struct [[gnu::packed]] ist_offset + { + /** + * @brief Default Constructor. + */ + ist_offset() = default; + + /** + * @brief Constructor. + * + * @param index Index into local or global descriptor table. + */ + ist_offset(uint8_t index); + + /** + * @brief Allows to compare the underlying set bits of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying set bits of both types are the same. + */ + auto operator==(ist_offset const & other) const -> bool = default; + + private: + uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. + }; +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_IST_OFFSET_HPP 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 new file mode 100644 index 0000000..c31e2d0 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp @@ -0,0 +1,74 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP + +#include +#include + +namespace teachos::arch::context_switching::interrupt_descriptor_table +{ + /** + * @brief Represents a segment selector in the x86_64 architecture, which points to a valid code segment in the global + * descriptor table. + * + * A segment selector is a 16-bit identifier used to select a segment descriptor + * from the Global Descriptor Table (GDT) or the Local Descriptor Table (LDT). + * It contains an index, a table indicator (TI), and a requested privilege level (RPL). + */ + struct [[gnu::packed]] segment_selector + { + /** + * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + */ + enum bitset : uint8_t + { + REQUEST_LEVEL_KERNEL = + 0U << 0U, ///< Highest privileged level used by the kernel to allow for full access of resources. + REQUEST_LEVEL_ADMIN = + 1U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + REQUEST_LEVEL_PRIVILEGED_USER = + 2U << 0U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more + ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. + REQUEST_LEVEL_USER = 3U << 0U, ///< Restricts access to only application and their specific memory. + LOCAL_DESCRIPTOR_TABLE = 1U << 2U, ///< Wheter the index referes to an entry in the local or global descriptor + ///< table. If enabled the index points to a local descriptor table, if it is + ///< cleared it referes to a global descriptor table instead. + }; + + /** + * @brief Default constructor. + */ + segment_selector() = default; + + /** + * @brief Constructor. + * + * @param index Index into the local or global descriptor table. + * @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. + */ + segment_selector(uint16_t index, uint8_t flags); + + /** + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * + * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng + * std::bitset. Any additional bits that are set are not relevant. + * + * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + */ + auto contains_flags(std::bitset<3U> other) const -> bool; + + /** + * @brief Defaulted three-way comparsion operator. + */ + 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. + }; +} // namespace teachos::arch::context_switching::interrupt_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_SEGMENT_SELECTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp index ef642d6..d2243ed 100644 --- a/arch/x86_64/include/arch/context_switching/main.hpp +++ b/arch/x86_64/include/arch/context_switching/main.hpp @@ -7,8 +7,7 @@ namespace teachos::arch::context_switching { /** - * @brief TODO - * + * @brief Contains the references to the tables required for context switching */ struct descriptor_tables { diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp index bbf3f49..3d7862c 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp @@ -43,17 +43,17 @@ namespace teachos::arch::context_switching::segment_descriptor_table INTERRUPT_GATE = 14, ///< The actual type of sytem segment is a interrupt gate. TRAP_GATE = 15, ///< The actual type of sytem segment is a trap gate. CODE_OR_DATA_SEGMENT = 1U << 4U, ///< Defines a system segment (if 0) or a code/data segment (if 1). - ACCESS_LEVEL_KERNEL = + DESCRIPTOR_LEVEL_KERNEL = 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. - ACCESS_LEVEL_ADMIN = + DESCRIPTOR_LEVEL_ADMIN = 1U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_PRIVILEGED_USER = + DESCRIPTOR_LEVEL_PRIVILEGED_USER = 2U << 5U, ///< Restricts access to own application and thoose of lower privilege. Should only be used if more ///< than two privilege levels are required, otherwise using Level 3 and Level 0 is recommended. - ACCESS_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory. - PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment. - ///< Must be set (1) for any valid segment. + DESCRIPTOR_LEVEL_USER = 3U << 5U, ///< Restricts access to only application and their specific memory. + PRESENT = 1U << 7U, ///< Present bit; Allows an entry to refer to a valid segment. + ///< Must be set (1) for any valid segment. }; /** @@ -90,7 +90,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table auto operator==(access_byte const & other) const -> bool = default; private: - uint8_t _flags = {}; ///< Underlying bitset used to read the flags from. + uint8_t _flags = {}; ///< Underlying bits used to read the flags from. }; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp index 2ce5286..fdf0044 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -78,8 +78,8 @@ namespace teachos::arch::context_switching::segment_descriptor_table auto operator==(gdt_flags const & other) const -> bool = default; private: - uint8_t _limit_2 : 4 = {}; - uint8_t _flags : 4 = {}; ///< Underlying bitset used to read the flags from. + uint8_t _limit_2 : 4 = {}; ///< Second part of the limit field. + uint8_t _flags : 4 = {}; ///< Underlying bits used to read the flags from. }; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp index a111a1f..f3067ba 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp @@ -6,42 +6,6 @@ namespace teachos::arch::context_switching::segment_descriptor_table { - enum class access_level - { - KERNEL, - USER - }; - - /** - * @brief Creates a generic segment_descriptor from the passed arguments. - * - * @param segment_descriptor_type Defines the type of the segment descriptor. - * @param access_level Defines the segment descriptor access level (KERNEL or USER). - * @return Created segment_descriptor. - */ - auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) - -> segment_descriptor; - - /** - * @brief Creates a global_descriptor_table on the heap and fills it with the following segment registers: - * - * - Kernel Code Segment - * - Kernel Data Segment - * - User Code Segment - * - User Data Segment - * - * @return Copy of the created global_descriptor_table. - */ - auto create_global_descriptor_table() -> global_descriptor_table; - - /** - * @brief Creates a task_state_segment segment_descriptor on the heap. - * - * @param tss task_state_segment whose pointer is used in the segment_descriptor - * @return Created segment_descriptor. - */ - auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor; - /** * @brief Initializes the global_descriptor_table and task_state_segment by loading them * in the GDTR and TR registers respectively. diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp index b66070b..13d6f53 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp @@ -8,7 +8,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table { - typedef stl::vector global_descriptor_table; + using global_descriptor_table = stl::vector; /** * @brief Represents a pointer to the Global Descriptor Table (GDT). diff --git a/arch/x86_64/include/arch/kernel/cpu/ss.hpp b/arch/x86_64/include/arch/kernel/cpu/ss.hpp index 1fb6448..b5fa5e3 100644 --- a/arch/x86_64/include/arch/kernel/cpu/ss.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/ss.hpp @@ -1,55 +1,26 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP #define TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" + #include #include namespace teachos::arch::kernel::cpu { - /** - * @brief Represents a segment selector in the x86_64 architecture. - * - * A segment selector is a 16-bit identifier used to select a segment descriptor - * from the Global Descriptor Table (GDT) or the Local Descriptor Table (LDT). - * It contains an index, a table indicator (TI), and a requested privilege level (RPL). - */ - struct segment_selector - { - /** - * @brief Constructs a segment selector. - * - * @param index The index of the segment descriptor. - * @param table_indicator The table indicator (0 for GDT, 1 for LDT). - * @param requested_privilege_level The requested privilege level (0-3). - */ - segment_selector(uint16_t index, std::bitset<1U> table_indicator, std::bitset<2U> requested_privilege_level); - - /** - * @brief Converts the segment selector to a 16-bit value. - * - * @return uint16_t The 16-bit representation of the segment selector. - */ - auto to_uint16() const -> uint16_t; - - private: - uint16_t index; - std::bitset<1U> table_indicator; - std::bitset<2U> requested_privilege_level; - }; - /** * @brief Reads the current value of the stack segment (SS) register. * - * @return uint16_t The current SS register value. + * @return The current SS register value. */ - auto read_ss() -> uint16_t; + auto read_ss() -> context_switching::interrupt_descriptor_table::segment_selector; /** * @brief Writes a new value to the stack segment (SS) register. * * @param selector The segment selector to be written to SS. */ - auto write_ss(segment_selector selector) -> void; + auto write_ss(context_switching::interrupt_descriptor_table::segment_selector selector) -> void; } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp index 7ea5517..cb6c5b3 100644 --- a/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp +++ b/arch/x86_64/include/arch/memory/allocator/physical_frame.hpp @@ -10,7 +10,7 @@ namespace teachos::arch::memory::allocator { - typedef std::size_t physical_address; + using physical_address = std::size_t; std::size_t constexpr PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. @@ -79,7 +79,7 @@ namespace teachos::arch::memory::allocator {}; ///< Index number of the current physical frame, used to distinguish it from other frames. }; - typedef stl::container> frame_container; + using frame_container = stl::container>; } // namespace teachos::arch::memory::allocator 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 4c7470b..730bcaf 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 @@ -162,7 +162,7 @@ namespace teachos::arch::memory::multiboot ///< contained in the section, to ensure byte alignment is actually 4 byte. }; - typedef stl::container> elf_section_header_container; + using elf_section_header_container = stl::container>; } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp index cc8db8c..68394c8 100644 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp @@ -46,7 +46,7 @@ namespace teachos::arch::memory::multiboot struct memory_area entries; ///< Specific memory regions. }; - typedef stl::container> memory_area_container; + using memory_area_container = stl::container>; } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp index d9164a0..a6c8c39 100644 --- a/arch/x86_64/include/arch/memory/paging/virtual_page.hpp +++ b/arch/x86_64/include/arch/memory/paging/virtual_page.hpp @@ -10,7 +10,7 @@ namespace teachos::arch::memory::paging { - typedef std::size_t virtual_address; + using virtual_address = std::size_t; /** * @brief Virtual page entry contained in P1 page tables @@ -84,7 +84,7 @@ namespace teachos::arch::memory::paging {}; ///< Index number of the current virtual page, used to distinguish it from other pages. }; - typedef stl::container> page_container; + using page_container = stl::container>; } // namespace teachos::arch::memory::paging -- cgit v1.2.3 From 96711d45ad7fb5b96cfd2b4fffda8756fe68fcd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 26 Mar 2025 09:33:44 +0000 Subject: Fixing pointer values and adding basic idt value --- .../interrupt_descriptor_table/gate_descriptor.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp index 196430f..a652e0c 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp @@ -57,11 +57,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table private: // The order in private variables starts for the first variable being the rightmost bit. - uint16_t _offset_1 = {}; ///< First part of the offset field (0 - 15) + uint16_t _offset_1 = {}; ///< First part of the offset field. Represents the address of the entry point of the + ///< Interrupt Service Routine. (0 - 15) segment_selector _selector = {}; ///< Segment selector (16 - 31) ist_offset _ist = {}; ///< Interrupt Stack Table offset (32 - 39) idt_flags _flags = {}; ///< Gate Type and Flags (40 - 47) - uint64_t _offset_2 : 48 = {}; ///< Second part of the offset field (48 - 95) + uint64_t _offset_2 : 48 = {}; ///< Second part of the offset field. Represents the address of the entry point of + ///< the Interrupt Service Routine. (48 - 95) uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::interrupt_descriptor_table -- cgit v1.2.3 From a6c5f6a273d0c5c4161f600fca6d4fe49858c23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 27 Mar 2025 09:40:32 +0000 Subject: Attempt to fix crash in far jump. WIP does not return from call to assembler method --- arch/x86_64/include/arch/boot/pointers.hpp | 2 +- .../interrupt_descriptor_table/segment_selector.hpp | 9 ++++++--- arch/x86_64/include/arch/kernel/cpu/if.hpp | 7 +++++++ arch/x86_64/include/arch/kernel/cpu/jmp.hpp | 14 ++++++++------ 4 files changed, 22 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/include') 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 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 -- cgit v1.2.3 From 9ddfcd02413a93718e8cde53f9ba5a96a5b29b8f Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Mar 2025 14:02:05 +0000 Subject: update long jump handling --- arch/x86_64/include/arch/boot/pointers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 5bcb792..5092fa6 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -13,7 +13,7 @@ namespace teachos::arch::boot /** * @brief Address pointing to the method that clears all segment registers. */ - extern "C" size_t const segment_register_reload_pointer; + extern "C" auto reload_segment_register_trampoline() -> void; } // namespace teachos::arch::boot -- cgit v1.2.3 From e0eae9b9e905a1842b333823bfdb7c253cda8d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 28 Mar 2025 09:59:09 +0000 Subject: Revert "update long jump handling" This reverts commit 9ddfcd02413a93718e8cde53f9ba5a96a5b29b8f. --- arch/x86_64/include/arch/boot/pointers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 5092fa6..5bcb792 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -13,7 +13,7 @@ namespace teachos::arch::boot /** * @brief Address pointing to the method that clears all segment registers. */ - extern "C" auto reload_segment_register_trampoline() -> void; + extern "C" size_t const segment_register_reload_pointer; } // namespace teachos::arch::boot -- cgit v1.2.3 From 437c3554f9a86b6347d97f5e2a82543c1e068b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 28 Mar 2025 10:52:25 +0000 Subject: Attempt to fix ljmp. Might not be possible in Long mode --- arch/x86_64/include/arch/boot/pointers.hpp | 2 +- arch/x86_64/include/arch/kernel/cpu/jmp.hpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 5bcb792..c08de52 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -13,7 +13,7 @@ namespace teachos::arch::boot /** * @brief Address pointing to the method that clears all segment registers. */ - extern "C" size_t const segment_register_reload_pointer; + extern "C" size_t reload_segment_register; } // namespace teachos::arch::boot diff --git a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp index 5bc7d07..163fac6 100644 --- a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp @@ -12,9 +12,9 @@ namespace teachos::arch::kernel::cpu */ struct [[gnu::packed]] far_pointer { - uint64_t offset; ///< Selector of the segment in which the jump occurs. (0- 63) + std::size_t function; ///< Address of the function we want to jump too. (0- 63) context_switching::interrupt_descriptor_table::segment_selector - selector; ///< Address to jump to within the segment. (64 - 79) + selector; ///< Segment selector that shows the segment we want to jump into. (64 - 79) }; /** @@ -22,7 +22,7 @@ namespace teachos::arch::kernel::cpu * * @param address Address we want to jump to. */ - auto jmp(uint64_t address) -> void; + auto jmp(std::size_t address) -> void; /** * @brief Far jump - A jump to an instruction located in a different segment than the current code segment but at the -- cgit v1.2.3 From fbd1ebe4f7c5985554fdca7c7fc05de15d47dd3a Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 28 Mar 2025 18:35:28 +0100 Subject: gdt: fix reload of GDT The core problems were/are the following: - The flags of the segments were not entirely correct. Please recheck them against the spec! - The GDT pointer did not contain the address of the first (null) GTD entry, but the address of the stl::vector containing the GDT entries. - The far pointer must consist of: - the address to jump to - the byte index into the GDT for the desired segement descriptor to be loaded into CS. - The type of the "dummy" function we jump to was wrong (it's a function, we should declare it as such). - We cannot enable interrupts right now, since we die with a triple fault. This is caused by some initia fault which seems to lead to a general protection fault, which then triple faults since we cannot find the IDT. Some FIXMEs have been added to the code. Please look at them carefully and compare things against the specs. --- arch/x86_64/include/arch/boot/pointers.hpp | 2 +- .../segment_descriptor_table/gdt_flags.hpp | 17 ++++++++++++----- .../global_descriptor_table_pointer.hpp | 4 ++-- arch/x86_64/include/arch/kernel/cpu/jmp.hpp | 7 +++---- 4 files changed, 18 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index c08de52..9bf5cfd 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -13,7 +13,7 @@ namespace teachos::arch::boot /** * @brief Address pointing to the method that clears all segment registers. */ - extern "C" size_t reload_segment_register; + extern "C" void reload_segment_register(); } // namespace teachos::arch::boot diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp index fdf0044..764aec5 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -18,17 +18,24 @@ namespace teachos::arch::context_switching::segment_descriptor_table */ enum bitset : uint8_t { - LENGTH = 1U << 0U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment - ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions are - ///< executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. If bis - ///< is set the DEFAULT_LENGTH bis needs to be 0 + LONG_MODE = 1U << 1U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment + ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions are + ///< executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. If bis + ///< is set the DEFAULT_LENGTH bis needs to be 0 + + // FIXME: Where does this come from, and is this value correct? UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 ///< GiB, 4 KiB otherwise. + + // FIXME: Where does this come from, and is this value correct? STACK_POINTER_SIZE = 1U << 1U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. + + // FIXME: Where does this come from, and is this value correct? DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and ///< operands. Enable for 32 bit, 16 bit otherwise. - GRANULARITY = 1U << 2U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte + + GRANULARITY = 1U << 3U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. }; diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp index 13d6f53..6fac2a0 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp @@ -26,7 +26,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table /** * @brief Constructor. */ - global_descriptor_table_pointer(uint16_t table_length, global_descriptor_table * address); + global_descriptor_table_pointer(uint16_t table_length, segment_descriptor * address); /** * @brief Defaulted three-way comparsion operator. @@ -35,7 +35,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table private: uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. - global_descriptor_table * address = {}; ///< Non-owning pointer to the GDT base address. + segment_descriptor * address = {}; ///< Non-owning pointer to the GDT base address. }; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp index 163fac6..0ed38e9 100644 --- a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp @@ -10,11 +10,10 @@ namespace teachos::arch::kernel::cpu /** * @brief Far jump - A jump to an instruction located in a different segment. */ - struct [[gnu::packed]] far_pointer + struct far_pointer { - std::size_t function; ///< Address of the function we want to jump too. (0- 63) - context_switching::interrupt_descriptor_table::segment_selector - selector; ///< Segment selector that shows the segment we want to jump into. (64 - 79) + void (*function)(); ///< Address of the function we want to jump too. (0-63) + std::uint16_t index; ///< Index of the GDT entry we want to load into register CS. (64-79) }; /** -- cgit v1.2.3 From aba154ad01fc0e1e1274f2582b1493e78daa2559 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 29 Mar 2025 14:47:04 +0000 Subject: fix gdt segments, improve idt and trial&error for triple fault --- .../interrupt_descriptor_table/gate_descriptor.hpp | 13 +++++----- .../interrupt_descriptor_table.hpp | 6 ++--- .../interrupt_descriptor_table_pointer.hpp | 12 +++++----- .../segment_descriptor_table/gdt_flags.hpp | 22 +++++++---------- .../generic_interrupt_handler.hpp | 28 ++++++++++++++++++++++ 5 files changed, 51 insertions(+), 30 deletions(-) create mode 100644 arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp index a652e0c..e677cbb 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp @@ -1,5 +1,5 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP #include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp" #include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp" @@ -57,15 +57,14 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table private: // The order in private variables starts for the first variable being the rightmost bit. - uint16_t _offset_1 = {}; ///< First part of the offset field. Represents the address of the entry point of the - ///< Interrupt Service Routine. (0 - 15) + uint16_t _offset_1 = {}; ///< Lower 16 bits of handler function address (0 - 15) segment_selector _selector = {}; ///< Segment selector (16 - 31) ist_offset _ist = {}; ///< Interrupt Stack Table offset (32 - 39) idt_flags _flags = {}; ///< Gate Type and Flags (40 - 47) - uint64_t _offset_2 : 48 = {}; ///< Second part of the offset field. Represents the address of the entry point of - ///< the Interrupt Service Routine. (48 - 95) + uint16_t _offset_2 = {}; ///< Middle 16 bits of handler function address (48 - 63) + uint32_t _offset_3 = {}; ///< Upper 32 bits of handler function address (for x86_64) (64 - 95) uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::interrupt_descriptor_table -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_GATE_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp index dd55cd7..e2ec4c5 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp @@ -1,5 +1,5 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP #include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp" @@ -15,4 +15,4 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table } // namespace teachos::arch::context_switching::interrupt_descriptor_table -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp index d853ff0..7fe933b 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp @@ -1,5 +1,5 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP #include "arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp" #include "arch/stl/vector.hpp" @@ -23,7 +23,7 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table /** * @brief Constructor. */ - interrupt_descriptor_table_pointer(uint16_t table_length, interrupt_descriptor_table * address); + interrupt_descriptor_table_pointer(uint16_t table_length, gate_descriptor * address); /** * @brief Defaulted three-way comparsion operator. @@ -31,10 +31,10 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table auto operator<=>(interrupt_descriptor_table_pointer const & other) const -> std::strong_ordering = default; private: - uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. - interrupt_descriptor_table * address = {}; ///< Non-owning pointer to the IDT base address. + uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. + gate_descriptor * address = {}; ///< Non-owning pointer to the IDT base address. }; } // namespace teachos::arch::context_switching::interrupt_descriptor_table -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_INTERRUPT_DESCRIPTOR_TABLE_INTERRUPT_DESCRIPTOR_TABLE_POINTER_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp index 764aec5..8217bcb 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -18,22 +18,16 @@ namespace teachos::arch::context_switching::segment_descriptor_table */ enum bitset : uint8_t { + AVAILABLE = 1U << 0U, ///< Available for use by System software. For our purposes this is basically reserved. LONG_MODE = 1U << 1U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment - ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions are - ///< executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. If bis - ///< is set the DEFAULT_LENGTH bis needs to be 0 + ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions + ///< are executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. + ///< If this is set the DEFAULT_OPERAND_SIZE/BIG bit needs to be clear (0). - // FIXME: Where does this come from, and is this value correct? - UPPER_BOUND = 1U << 1U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 5 - ///< GiB, 4 KiB otherwise. - - // FIXME: Where does this come from, and is this value correct? - STACK_POINTER_SIZE = 1U << 1U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for - ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. - - // FIXME: Where does this come from, and is this value correct? - DEFAULT_LENGTH = 1U << 1U, ///< Indicates the default length for code segments with effective addresses and - ///< operands. Enable for 32 bit, 16 bit otherwise. + DEFAULT_OPERATION_SIZE = + 1U << 2U, ///< If clear, this is a 16-bit code segment; if set, this is a 32-bit segment. + BIG = 1U << 2U, ///< If set, the maximum offset size for a data segment is increased to 32-bit + ///< 0xffffffff. Otherwise it's the 16-bit max 0x0000ffff. Essentially the same meaning as "D". GRANULARITY = 1U << 3U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp new file mode 100644 index 0000000..9f33fa0 --- /dev/null +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -0,0 +1,28 @@ +#ifndef TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP +#define TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP + +#include + +namespace teachos::arch::interrupt_handling +{ + /** + * @brief This has been created in a rush. I think it is correct + * + * TODO: Create doxygen + * + */ + struct interrupt_frame + { + uint64_t ip; ///< Dummy + uint64_t cs; ///< Dummy + uint64_t flags; ///< Dummy + uint64_t sp; ///< Dummy + uint64_t ss; ///< Dummy + }; + + [[gnu::interrupt]] + auto generic_interrupt_handler(struct interrupt_frame * frame) -> void; + +} // namespace teachos::arch::interrupt_handling + +#endif // TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP -- cgit v1.2.3 From abe7bd7480c8f4e1e30b9f0f3b98966222817f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 31 Mar 2025 10:38:53 +0000 Subject: Clean up global descriptor table initalization --- .../interrupt_descriptor_table/gate_descriptor.hpp | 3 +-- .../interrupt_descriptor_table.hpp | 12 ++++++++--- .../segment_descriptor_table/gdt_flags.hpp | 15 +++++++------- .../global_descriptor_table.hpp | 24 +++++++++++++++++++--- arch/x86_64/include/arch/kernel/cpu/jmp.hpp | 3 ++- 5 files changed, 40 insertions(+), 17 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp index e677cbb..22cd0f0 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp @@ -61,8 +61,7 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table segment_selector _selector = {}; ///< Segment selector (16 - 31) ist_offset _ist = {}; ///< Interrupt Stack Table offset (32 - 39) idt_flags _flags = {}; ///< Gate Type and Flags (40 - 47) - uint16_t _offset_2 = {}; ///< Middle 16 bits of handler function address (48 - 63) - uint32_t _offset_3 = {}; ///< Upper 32 bits of handler function address (for x86_64) (64 - 95) + uint64_t _offset_2 : 48 = {}; ///< Upper 48 bits of handler function address (48 - 95) uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp index e2ec4c5..b388e0e 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp @@ -6,12 +6,18 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { /** - * @brief Initializes the interrupt_descriptor_table by loading it - * in the IDTR register. + * @brief Updates the IDTR with the created interrupt descriptor table. If it has not been created yet this + * method will create it. + */ + auto update_interrupt_descriptor_table_register() -> void; + + /** + * @brief Creates the interrupt descriptor table, with the minimum required configuration. If this method is called + * more than once, the previously created instance is returned instead. * * @return Reference to the created interrupt_descriptor_table. */ - auto initialize_interrupt_descriptor_table() -> interrupt_descriptor_table &; + auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table &; } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp index 8217bcb..d8c3cd1 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -18,17 +18,16 @@ namespace teachos::arch::context_switching::segment_descriptor_table */ enum bitset : uint8_t { - AVAILABLE = 1U << 0U, ///< Available for use by System software. For our purposes this is basically reserved. LONG_MODE = 1U << 1U, ///< Defines in IA-32e mode (64-bit code and 32-bit compatability mode) if the segment ///< contains 64-bit code. Otherwise this bit should always be 0. Enable if instructions ///< are executed in 64-bit code, otherwise they are executed in compatability 32-bit mode. - ///< If this is set the DEFAULT_OPERAND_SIZE/BIG bit needs to be clear (0). - - DEFAULT_OPERATION_SIZE = - 1U << 2U, ///< If clear, this is a 16-bit code segment; if set, this is a 32-bit segment. - BIG = 1U << 2U, ///< If set, the maximum offset size for a data segment is increased to 32-bit - ///< 0xffffffff. Otherwise it's the 16-bit max 0x0000ffff. Essentially the same meaning as "D". - + ///< If this bit is set the 3rd bit needs to be clear (0). + UPPER_BOUND = 1U << 2U, ///< Specifies the upper bound of the segment for expand down data segment. Enable for 4 + ///< GiB, 4 KiB otherwise. + STACK_POINTER_SIZE = 1U << 2U, ///< Specifies the size of the Stack Pointer (SP) for stack segments used for + ///< implicit stack operations. Enable for 32 bit, 16 bit otherwise. + DEFAULT_LENGTH = 1U << 2U, ///< Indicates the default length for code segments with effective addresses and + ///< operands. Enable for 32 bit, 16 bit otherwise. GRANULARITY = 1U << 3U, ///< Indicates the size the Limit value in the segment descriptor is scaled by 1 Byte ///< blocks if the bit is not set or by 4 KiB blocks if the bit is set. }; diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp index f3067ba..bd69a46 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp @@ -7,12 +7,30 @@ namespace teachos::arch::context_switching::segment_descriptor_table { /** - * @brief Initializes the global_descriptor_table and task_state_segment by loading them - * in the GDTR and TR registers respectively. + * @brief Creates the global descriptor table, with the minimum required configuration. If this method is called more + * than once, the previously created instance is returned instead. * * @return Reference to the created global_descriptor_table. */ - auto initialize_global_descriptor_table() -> global_descriptor_table &; + auto get_or_create_global_descriptor_table() -> global_descriptor_table &; + + /** + * @brief Updates the GDTR with the created global descriptor table. If it has not been created yet this + * method will create it. + * + * @note This method will only set the GDTR, but for the processor to actually register the change a far jump + * has to be executed. This also has to be done before updating the TR. + */ + auto update_global_descriptor_table_register() -> void; + + /** + * @brief Updates the TR with the created task state segment. If it has not been created yet this + * method will create it. + * + * @note This method should only be called after update_global_descriptor_table_register() and a far jump has been + * executed. Because before that trying to access the segment will cause an exception. + */ + auto update_task_state_segment_register() -> void; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp index 0ed38e9..1657c18 100644 --- a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp @@ -13,7 +13,8 @@ namespace teachos::arch::kernel::cpu struct far_pointer { void (*function)(); ///< Address of the function we want to jump too. (0-63) - std::uint16_t index; ///< Index of the GDT entry we want to load into register CS. (64-79) + context_switching::interrupt_descriptor_table::segment_selector + selector; ///< Segment selector pointing to the GDT entry we want to load into register CS. (64-79) }; /** -- cgit v1.2.3 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.hpp | 15 +++++++++++---- .../interrupt_descriptor_table/segment_selector.hpp | 15 +++++++++++---- .../segment_descriptor_table/access_byte.hpp | 19 +++++++++++++------ .../segment_descriptor_table/gdt_flags.hpp | 15 +++++++++++---- 4 files changed, 46 insertions(+), 18 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp index f153e36..2f8e61d 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp @@ -48,13 +48,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table idt_flags(uint8_t flags); /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data. * * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng - * std::bitset. Any additional bits that are set are not relevant. + * data. Any additional bits that are set are not relevant. * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + * @param other Flags that we want to compare against and check if the underlying data has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying data. */ auto contains_flags(std::bitset<8U> other) const -> bool; @@ -66,6 +66,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ auto operator==(idt_flags const & other) const -> bool = default; + /** + * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data. + * + * @param other Additional bits that should be set. + */ + auto operator|=(std::bitset<8U> other) -> void; + private: uint8_t _flags = {}; ///< Underlying bits used to read the flags from. }; 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 73cd176..2c90152 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 @@ -51,13 +51,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table segment_selector(uint16_t index, uint8_t flags); /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data. * * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng - * std::bitset. Any additional bits that are set are not relevant. + * data. Any additional bits that are set are not relevant. * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + * @param other Flags that we want to compare against and check if the underlying data has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying data. */ auto contains_flags(std::bitset<3U> other) const -> bool; @@ -66,6 +66,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ auto operator<=>(segment_selector const & other) const -> std::strong_ordering = default; + /** + * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data. + * + * @param other Additional bits that should be set. + */ + auto operator|=(std::bitset<3U> other) -> void; + private: uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from. uint16_t _index : 13 = diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp index 3d7862c..621b570 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp @@ -71,24 +71,31 @@ namespace teachos::arch::context_switching::segment_descriptor_table access_byte(uint8_t flags); /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data. * * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng - * std::bitset. Any additional bits that are set are not relevant. + * data. Any additional bits that are set are not relevant. * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + * @param other Flags that we want to compare against and check if the underlying data has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying data. */ auto contains_flags(std::bitset<8U> other) const -> bool; /** - * @brief Allows to compare the underlying std::bitset of two instances. + * @brief Allows to compare the underlying data of two instances. * * @param other Other instance that we want to compare with. - * @return Whether the underlying std::bitset of both types is the same. + * @return Whether the underlying data of both types is the same. */ auto operator==(access_byte const & other) const -> bool = default; + /** + * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data. + * + * @param other Additional bits that should be set. + */ + auto operator|=(std::bitset<8U> other) -> void; + private: uint8_t _flags = {}; ///< Underlying bits used to read the flags from. }; diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp index d8c3cd1..4b84035 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -50,13 +50,13 @@ namespace teachos::arch::context_switching::segment_descriptor_table gdt_flags(uint8_t flags, std::bitset<20U> limit); /** - * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset. + * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data. * * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng - * std::bitset. Any additional bits that are set are not relevant. + * data. Any additional bits that are set are not relevant. * - * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set. - * @return Whether the given flags are a subset or equivalent with the underlying std::bitset. + * @param other Flags that we want to compare against and check if the underlying data has the same bits set. + * @return Whether the given flags are a subset or equivalent with the underlying data. */ auto contains_flags(std::bitset<4U> other) const -> bool; @@ -77,6 +77,13 @@ namespace teachos::arch::context_switching::segment_descriptor_table */ auto operator==(gdt_flags const & other) const -> bool = default; + /** + * @brief Combines all bits that are set in the std::bitset flags with the bits already set in the underlying data. + * + * @param other Additional bits that should be set. + */ + auto operator|=(std::bitset<4U> other) -> void; + private: uint8_t _limit_2 : 4 = {}; ///< Second part of the limit field. uint8_t _flags : 4 = {}; ///< Underlying bits used to read the flags from. -- cgit v1.2.3 From 6878ffae67a6940ab8dca9831abf9537322ed2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 1 Apr 2025 13:35:49 +0000 Subject: Fix invalid type field of gate descriptor --- .../arch/context_switching/interrupt_descriptor_table/idt_flags.hpp | 4 ++-- .../arch/context_switching/interrupt_descriptor_table/ist_offset.hpp | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp index 2f8e61d..4e8b32c 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp @@ -18,8 +18,8 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ enum bitset : uint8_t { - INTERRUPT_GATE = 16U, ///< The actual type of gate segment is a interrupt gate. - TRAP_GATE = 17U, ///< The actual type of gate segment is a trap gate. + INTERRUPT_GATE = 0b1110, ///< The actual type of gate segment is a interrupt gate. + TRAP_GATE = 0b1111, ///< The actual type of gate segment is a trap gate. DESCRIPTOR_LEVEL_KERNEL = 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. DESCRIPTOR_LEVEL_ADMIN = diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp index f31a898..cefe1b2 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp @@ -34,7 +34,9 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table auto operator==(ist_offset const & other) const -> bool = default; private: - uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. + uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. A value of of 0 menas we do not switch stacks, + ///< whereas 1 - 7 mean we switch to the n-th stack in the Interrupt Stack Table, contained + ///< in the TSS if the gate descriptor that contains this field is called. }; } // namespace teachos::arch::context_switching::interrupt_descriptor_table -- cgit v1.2.3 From fc4a2306b803ccfc27f1bdc4a831176a5278a9d5 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Wed, 2 Apr 2025 09:57:54 +0000 Subject: fix interrupt handler and idt --- .../arch/interrupt_handling/generic_interrupt_handler.hpp | 11 ++++++----- .../include/arch/memory/multiboot/elf_symbols_section.hpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index 9f33fa0..d828c50 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -13,11 +13,12 @@ namespace teachos::arch::interrupt_handling */ struct interrupt_frame { - uint64_t ip; ///< Dummy - uint64_t cs; ///< Dummy - uint64_t flags; ///< Dummy - uint64_t sp; ///< Dummy - uint64_t ss; ///< Dummy + uint64_t error_code; ///< Error Code (TODO: Potential mistake -> some interrupts contain this field and some dont?) + uint64_t ip; ///< Instruction pointer + uint64_t cs; ///< Code segment + uint64_t flags; ///< RFLAGS + uint64_t sp; ///< Stack pointer + uint64_t ss; ///< Stack segment }; [[gnu::interrupt]] 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 730bcaf..0a25ca9 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 @@ -20,7 +20,7 @@ namespace teachos::arch::memory::multiboot INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out. PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE). SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table. - STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and deubbging null-terminated strings. + STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and debugging null-terminated strings. RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems. SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols. DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information. -- cgit v1.2.3 From f19681f4dfaaa0bdd3f22e76c48abda3c68bfe0c Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 3 Apr 2025 08:59:50 +0000 Subject: add documentation to interrupt handler --- .../generic_interrupt_handler.hpp | 25 +++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index d828c50..6c1db12 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -6,21 +6,26 @@ namespace teachos::arch::interrupt_handling { /** - * @brief This has been created in a rush. I think it is correct - * - * TODO: Create doxygen + * @brief Represents the CPU state during an interrupt. * + * Some interrupts push an error code, while others do not. The full list + * of which vector number contains the error code can be found here: https://wiki.osdev.org/Exceptions */ - struct interrupt_frame + struct [[gnu::packed]] interrupt_frame { - uint64_t error_code; ///< Error Code (TODO: Potential mistake -> some interrupts contain this field and some dont?) - uint64_t ip; ///< Instruction pointer - uint64_t cs; ///< Code segment - uint64_t flags; ///< RFLAGS - uint64_t sp; ///< Stack pointer - uint64_t ss; ///< Stack segment + uint64_t error_code; ///< Error code pushed by some exceptions. + uint64_t ip; ///< Instruction pointer at the time of the interrupt. + uint64_t cs; ///< Code segment selector indicating privilege level. + uint64_t flags; ///< CPU flags (RFLAGS) storing processor state. + uint64_t sp; ///< Stack pointer at the time of the interrupt. + uint64_t ss; ///< Stack segment selector, usually unused in 64-bit mode. }; + /** + * @brief Generic interrupt handler function. + * + * @param frame Pointer to the interrupt frame containing CPU state. + */ [[gnu::interrupt]] auto generic_interrupt_handler(struct interrupt_frame * frame) -> void; -- cgit v1.2.3 From 8b66e4cd1d1487fefbae459f556396db61497a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 4 Apr 2025 15:05:59 +0000 Subject: Multiplication by two for segment selector index --- .../interrupt_descriptor_table/segment_selector.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') 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 2c90152..b31f9e8 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,8 +43,12 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table /** * @brief Constructor. * - * @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 index Index into the local or global descriptor table. Processor multiplies the index value by 8 (number + * of bytes in 32-bit segment descriptor) and adds the result to the base GDT or LDT address. Because it only + * multiplies by 8, but we are using long mode the constructor additionally multiplies the given value by two. This + * is done because 64-bit segment descriptor are twice as big in size. If we wouldn't multiply by two, index 1 would + * result in the middle between the second part of the null entry and the first part of the code kernel segment and + * therefore be invalid. * @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. */ -- cgit v1.2.3 From a8852f91967a7e55e62e30f5cc07d076092b8b78 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 5 Apr 2025 15:27:20 +0000 Subject: add wip context switch to user mode --- arch/x86_64/include/arch/boot/pointers.hpp | 5 ---- .../include/arch/kernel/cpu/segment_register.hpp | 23 ++++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/ss.hpp | 27 ---------------------- 3 files changed, 23 insertions(+), 32 deletions(-) create mode 100644 arch/x86_64/include/arch/kernel/cpu/segment_register.hpp delete mode 100644 arch/x86_64/include/arch/kernel/cpu/ss.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 9bf5cfd..fe9c657 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -10,11 +10,6 @@ namespace teachos::arch::boot */ extern "C" size_t const multiboot_information_pointer; - /** - * @brief Address pointing to the method that clears all segment registers. - */ - extern "C" void reload_segment_register(); - } // namespace teachos::arch::boot #endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp new file mode 100644 index 0000000..bd244fd --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -0,0 +1,23 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP + +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" + +namespace teachos::arch::kernel::cpu +{ + /** + * @brief Clear all segment registers. + */ + [[gnu::naked]] + auto reload_segment_registers() -> void; + + /** + * @brief Set the value of all segment registers. + * + * @param segment_selector + */ + auto set_segment_registers(context_switching::interrupt_descriptor_table::segment_selector segment_selector) -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/ss.hpp b/arch/x86_64/include/arch/kernel/cpu/ss.hpp deleted file mode 100644 index b5fa5e3..0000000 --- a/arch/x86_64/include/arch/kernel/cpu/ss.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP -#define TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP - -#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" - -#include -#include - -namespace teachos::arch::kernel::cpu -{ - /** - * @brief Reads the current value of the stack segment (SS) register. - * - * @return The current SS register value. - */ - auto read_ss() -> context_switching::interrupt_descriptor_table::segment_selector; - - /** - * @brief Writes a new value to the stack segment (SS) register. - * - * @param selector The segment selector to be written to SS. - */ - auto write_ss(context_switching::interrupt_descriptor_table::segment_selector selector) -> void; - -} // namespace teachos::arch::kernel::cpu - -#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SS_HPP -- cgit v1.2.3 From 350aedae0e50749f9821ac7dc6b8316cf35f24bb Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 6 Apr 2025 07:47:27 +0000 Subject: wip context switch in asm --- arch/x86_64/include/arch/boot/pointers.hpp | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index fe9c657..f0878f9 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -9,6 +9,7 @@ namespace teachos::arch::boot * @brief Address pointing to the start of the multiboot information structure. */ extern "C" size_t const multiboot_information_pointer; + extern "C" auto context_switch() -> void; } // namespace teachos::arch::boot -- cgit v1.2.3 From 3a95e601bbcb64fd80d9d5d9bd6e1f6d3c31a89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 7 Apr 2025 15:05:30 +0000 Subject: Adjust idt flags bitset --- .../arch/context_switching/interrupt_descriptor_table/idt_flags.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp index 4e8b32c..948f478 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp @@ -18,8 +18,8 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ enum bitset : uint8_t { - INTERRUPT_GATE = 0b1110, ///< The actual type of gate segment is a interrupt gate. - TRAP_GATE = 0b1111, ///< The actual type of gate segment is a trap gate. + INTERRUPT_GATE = 0b01110, ///< The actual type of gate segment is a interrupt gate. + TRAP_GATE = 0b01111, ///< The actual type of gate segment is a trap gate. DESCRIPTOR_LEVEL_KERNEL = 0U << 5U, ///< Highest privileged level used by the kernel to allow for full access of resources. DESCRIPTOR_LEVEL_ADMIN = -- cgit v1.2.3 From 8a23a47425162894141f4eac488fb1f1bb3f7dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 7 Apr 2025 15:42:38 +0000 Subject: Fix naming from jmp to call for Far Call --- arch/x86_64/include/arch/kernel/cpu/call.hpp | 30 ++++++++++++++++++++++ arch/x86_64/include/arch/kernel/cpu/jmp.hpp | 37 ---------------------------- 2 files changed, 30 insertions(+), 37 deletions(-) create mode 100644 arch/x86_64/include/arch/kernel/cpu/call.hpp delete mode 100644 arch/x86_64/include/arch/kernel/cpu/jmp.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/kernel/cpu/call.hpp b/arch/x86_64/include/arch/kernel/cpu/call.hpp new file mode 100644 index 0000000..3c43304 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/cpu/call.hpp @@ -0,0 +1,30 @@ +#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 + +namespace teachos::arch::kernel::cpu +{ + /** + * @brief Far Pointer. Address to function located in another code segment. + */ + struct far_pointer + { + void (*function)(); ///< Address of the function we want to call. (0-63) + context_switching::interrupt_descriptor_table::segment_selector + selector; ///< Segment selector pointing to the GDT entry we want to load into register CS. (64-79) + }; + + /** + * @brief Far call - A call to an instruction located in a different segment than the current code segment but at the + * same privilege level. + * + * @param pointer 64-bit operand size far pointer that we want to call. + */ + auto call(far_pointer pointer) -> void; + +} // namespace teachos::arch::kernel::cpu + +#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp deleted file mode 100644 index 1657c18..0000000 --- a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#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 - -namespace teachos::arch::kernel::cpu -{ - /** - * @brief Far jump - A jump to an instruction located in a different segment. - */ - struct far_pointer - { - void (*function)(); ///< Address of the function we want to jump too. (0-63) - context_switching::interrupt_descriptor_table::segment_selector - selector; ///< Segment selector pointing to the GDT entry we want to load into register CS. (64-79) - }; - - /** - * @brief Near jump - A jump to an instruction within the current code segment. - * - * @param address Address we want to jump to. - */ - auto jmp(std::size_t address) -> void; - - /** - * @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 pointer 64-bit operand size far pointer that we should jump too. - */ - auto jmp(far_pointer pointer) -> void; - -} // namespace teachos::arch::kernel::cpu - -#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP -- cgit v1.2.3 From f3d84e8645e1f6318c7e34f3524cd332ac6deef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 10 Apr 2025 07:55:30 +0000 Subject: Remove zombie code --- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/x86_64/include') 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 da3c8ff..377533c 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 @@ -116,9 +116,6 @@ namespace teachos::arch::memory::heap memory_block * first; ///< First free entry in our memory. stl::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. }; - - extern linked_list_allocator kernel_heap; - } // namespace teachos::arch::memory::heap #endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP -- cgit v1.2.3 From 62d7fa83e831e84ea851d97b5c957146880ad69a Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 10 Apr 2025 10:28:46 +0000 Subject: move context_switch function into cpp code --- arch/x86_64/include/arch/boot/pointers.hpp | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index f0878f9..fe9c657 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -9,7 +9,6 @@ namespace teachos::arch::boot * @brief Address pointing to the start of the multiboot information structure. */ extern "C" size_t const multiboot_information_pointer; - extern "C" auto context_switch() -> void; } // namespace teachos::arch::boot -- cgit v1.2.3 From dff78de795a89c181e9c94b26db2f16988e8f4d6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 10 Apr 2025 12:11:55 +0000 Subject: move context_switch function and environment into different directory --- .../segment_selector.hpp | 7 ++++++- .../x86_64/include/arch/context_switching/main.hpp | 24 ++++++++++++++++++++++ .../include/arch/kernel/cpu/segment_register.hpp | 9 +++++++- 3 files changed, 38 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') 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 b31f9e8..e8854f9 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 @@ -52,7 +52,12 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table * @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. */ - segment_selector(uint16_t index, uint8_t flags); + constexpr segment_selector(uint16_t index, uint8_t flags) + : _flags(flags) + , _index(index * 2U) + { + // Nothing to do. + } /** * @brief Checks if the given std::bitset is a subset or equivalent to the underlying data. diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp index d2243ed..e296457 100644 --- a/arch/x86_64/include/arch/context_switching/main.hpp +++ b/arch/x86_64/include/arch/context_switching/main.hpp @@ -15,8 +15,32 @@ namespace teachos::arch::context_switching interrupt_descriptor_table::interrupt_descriptor_table & idt; ///< Reference to the interrupt descriptor table. }; + /** + * @brief Setup GDT and IDT TODO + * + * @return descriptor_tables + */ auto initialize_descriptor_tables() -> descriptor_tables; + /** + * @brief TODO + * + * @param data_segment + * @param code_segment + * @param return_function + */ + auto switch_to_user_mode() -> void; + + /** + * @brief TODO + * + * @param data_segment + * @param code_segment + * @param return_function + */ + auto switch_context(interrupt_descriptor_table::segment_selector data_segment, + interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void; + } // namespace teachos::arch::context_switching #endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp index bd244fd..fd5a972 100644 --- a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -12,12 +12,19 @@ namespace teachos::arch::kernel::cpu auto reload_segment_registers() -> void; /** - * @brief Set the value of all segment registers. + * @brief Set the value of all segment registers. TODO * * @param segment_selector */ auto set_segment_registers(context_switching::interrupt_descriptor_table::segment_selector segment_selector) -> void; + /** + * @brief Returns the segment_selector in the code segment (cs) register. TODO + * + * @return segment_selector in the cs register + */ + auto read_code_segment_register() -> context_switching::interrupt_descriptor_table::segment_selector; + } // namespace teachos::arch::kernel::cpu #endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP -- cgit v1.2.3 From 87091e2246d2c4c794d9d6a0c5398ca80d92335a Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 10 Apr 2025 12:29:19 +0000 Subject: add register validation and asserts --- arch/x86_64/include/arch/kernel/cpu/segment_register.hpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp index fd5a972..d495ce6 100644 --- a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -25,6 +25,12 @@ namespace teachos::arch::kernel::cpu */ auto read_code_segment_register() -> context_switching::interrupt_descriptor_table::segment_selector; + /** + * @brief TODO + * + */ + auto validate_data_segment_registers() -> context_switching::interrupt_descriptor_table::segment_selector; + } // namespace teachos::arch::kernel::cpu #endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_SEGMENT_REGISTER_HPP -- cgit v1.2.3 From 9a185c1533bd2197d0e830369b4cc26abf88e2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 11 Apr 2025 09:25:04 +0000 Subject: Document methods and move them into kernel cpu folder --- .../x86_64/include/arch/context_switching/main.hpp | 27 +++++--- .../include/arch/kernel/cpu/segment_register.hpp | 80 +++++++++++++++++++--- 2 files changed, 86 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp index e296457..f8477ea 100644 --- a/arch/x86_64/include/arch/context_switching/main.hpp +++ b/arch/x86_64/include/arch/context_switching/main.hpp @@ -16,27 +16,32 @@ namespace teachos::arch::context_switching }; /** - * @brief Setup GDT and IDT TODO + * @brief Creates the Interrupt Descriptor Table and Global Descriptor Table as a static variable the first time this + * method is called and update IDTR and GDTR registers values. * - * @return descriptor_tables + * @note Subsequent calls after the first one, will simply return the previously created tables, but not update the + * registers again. + * + * @return References to the statically created Interrupt Descriptor and Global Descriptor Table. */ auto initialize_descriptor_tables() -> descriptor_tables; /** - * @brief TODO - * - * @param data_segment - * @param code_segment - * @param return_function + * @brief Switches from the current Kernel Mode (Level 0) to User Mode (Level 3). Will simply use predefined Segment + * Selectors for the User Data and User Code Segment, which are Index 3 and 4 in the GDT respectively. */ auto switch_to_user_mode() -> void; /** - * @brief TODO + * @brief Switches from the current Code and Data Segment to the given Code and Data Segment. + * + * @note This method will additionally call initialize_descriptor_tables, to ensure the GDTR and IDTR have been setup + * correctly before attempting to switch the context. This switch is achieved using a far return, which will once + * executed call the given void function. * - * @param data_segment - * @param code_segment - * @param return_function + * @param data_segment Data Segment that the SS, DS; ES, FS and GS register will be set too. + * @param code_segment Code Segment that the CS register will be set too. + * @param return_function Function that will be called once the switch has been achieved. */ auto switch_context(interrupt_descriptor_table::segment_selector data_segment, interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void; diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp index d495ce6..5c77206 100644 --- a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -6,30 +6,90 @@ namespace teachos::arch::kernel::cpu { /** - * @brief Clear all segment registers. + * @brief Clear all Data Segment registers (DS / ES / FS / GS). */ - [[gnu::naked]] - auto reload_segment_registers() -> void; + auto reload_data_segment_registers() -> void; /** - * @brief Set the value of all segment registers. TODO + * @brief Updates the value of the Data Segment Register (DS), Extra Segment Register (ES), Thread-Local Storage + * Registers (FS / GS). * - * @param segment_selector + * @note The Stack Segment Register (SS) value should also be updated, but the value can not be directly set in + * comparsion to the other registers. This is the case because the register is used for stack management and can not + * be directly changed, instead this has to be done by a special instruction. Therefore + * validate_data_segment_registers should only be called after set_code_segment_register has been called as well. + * + * @param segment_selector Data Segment that should be loaded into the registers. */ - auto set_segment_registers(context_switching::interrupt_descriptor_table::segment_selector segment_selector) -> void; + auto set_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector segment_selector) + -> void; /** - * @brief Returns the segment_selector in the code segment (cs) register. TODO + * @brief Returns the Segment Selector pointing to the Code Segment that has been loaded into the Code Segment + * Register (CS). + * + * @note The CS register can not be directly changed, instead a Far Return has to be executed to change it * - * @return segment_selector in the cs register + * @return Segment Selector pointing to the currently loaded Code Segment. */ auto read_code_segment_register() -> context_switching::interrupt_descriptor_table::segment_selector; /** - * @brief TODO + * @brief Validates that all Data Segment Registers (DS / ES / FS / GS / SS) are the same as the given Data Segment + * and asserts and stops the application if they are not. + * + * @note This is only the case after set_code_segment_register has been executed as well, because it makes a far + * return that updates the SS register. + * + * @param data_segment Value that should be loaded into all Data Segment Registers. + */ + auto validate_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment) + -> void; + + /** + * @brief Validates that the Code Segment Register (CS) is the same as the given Code Segment + * and asserts and stops the application if they are not. + * + * @param code_segment Value that should be loaded into the Code Segment Register. + */ + auto validate_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector code_segment) + -> void; + + /** + * @brief Simply forwards the call to validate_data_segment_registers and validate_code_segment_register and ensures + * that all Segment Registers, have been configured correctly. + * + * @note If all Segment Register have been set correctly the Context Switch using the set_code_segment_register method + * was successfull and the Privilege Level has been changed. + * + * @param data_segment Value that should be loaded into all Data Segment Registers. + * @param code_segment Value that should be loaded into the Code Segment Register. + */ + auto validate_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment, + context_switching::interrupt_descriptor_table::segment_selector code_segment) -> void; + + /** + * @brief Sets the value of the Code Segment Register (CS), this is achieved using a Far Return. + * + * @note The Far Return used by this method, will cause the context to switch, because we are changing from the + * current Code Segment and it's associated Privilege Level to another Code Segment. The given method will then be + * called in the new context and it should be possible to call validate_segment_registers, with the same values + * without assertions if the switch was successful. + * + * To achieve this Far Return we call IRETQ, which expects the stack to be defined a certain way to achieve that we: + * 1. Push the Data Segment Selector + * 2. Push the current Stack Pointer + * 3. Push Eflags + * 4. Push Code Segment Selector + * 5. Push Return Address * + * @param data_segment Data Segment that should be loaded into the SS register. + * @param code_segment Code Segment that should be loaded into the CS register. + * @param address Function that we want to call in the new context created by the given Code Segment. */ - auto validate_data_segment_registers() -> context_switching::interrupt_descriptor_table::segment_selector; + auto set_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector data_segment, + context_switching::interrupt_descriptor_table::segment_selector code_segment, + uint64_t address) -> void; } // namespace teachos::arch::kernel::cpu -- cgit v1.2.3 From 3c7250a32033700944ed6f3d2174756245b22e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 11 Apr 2025 13:37:55 +0000 Subject: Adjust variable name --- arch/x86_64/include/arch/kernel/cpu/segment_register.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp index 5c77206..6a2ca3e 100644 --- a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -19,10 +19,9 @@ namespace teachos::arch::kernel::cpu * be directly changed, instead this has to be done by a special instruction. Therefore * validate_data_segment_registers should only be called after set_code_segment_register has been called as well. * - * @param segment_selector Data Segment that should be loaded into the registers. + * @param data_segment Value that should be loaded into the registers. */ - auto set_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector segment_selector) - -> void; + auto set_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment) -> void; /** * @brief Returns the Segment Selector pointing to the Code Segment that has been loaded into the Code Segment -- cgit v1.2.3 From eafe8533bb5ccbe15bd8ffbc917b38122b04a157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Apr 2025 15:21:52 +0000 Subject: Add stack frame allocator. Fix stl vector bug and create stl stack implementation --- .../arch/memory/allocator/area_frame_allocator.hpp | 2 +- .../memory/allocator/stack_frame_allocator.hpp | 67 ++++++++ .../arch/memory/heap/global_heap_allocator.hpp | 2 +- arch/x86_64/include/arch/stl/stack.hpp | 179 +++++++++++++++++++++ arch/x86_64/include/arch/stl/vector.hpp | 82 +++++++--- 5 files changed, 305 insertions(+), 27 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp create mode 100644 arch/x86_64/include/arch/stl/stack.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp index b8370db..2244613 100644 --- a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp @@ -55,7 +55,7 @@ namespace teachos::arch::memory::allocator physical_frame next_free_frame; ///< The physical_frame after the last allocated one. std::optional current_area; ///< The current memory area. multiboot::memory_area_container const - memory_areas; ///< All memory areas in custom container allows to use std::ranges + memory_areas; ///< All memory areas in custom container allows to use std::ranges. physical_frame const kernel_start; ///< The start address of the kernel code in memory. physical_frame const kernel_end; ///< The end address of the kernel code in memory. physical_frame const multiboot_start; ///< The start address of the multiboot code in memory. diff --git a/arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp new file mode 100644 index 0000000..a8e7233 --- /dev/null +++ b/arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp @@ -0,0 +1,67 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_STACK_FRAME_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_STACK_FRAME_ALLOCATOR_HPP + +#include "arch/memory/allocator/physical_frame.hpp" +#include "arch/memory/multiboot/reader.hpp" +#include "arch/stl/stack.hpp" + +#include + +namespace teachos::arch::memory::allocator +{ + /** + * @brief Uses an internal stack-like dynamic structure to keep track of the address of all avaialable physical frames + * that are available using the memory areas read from the multiboot2 information pointer and simply pushes + * deallocated frames back onto the stack. Allows for constant speed O(1) allocation and deallocation + */ + struct stack_frame_allocator + { + /** + * @brief Constructor + * + * @param mem_info Structure containg all relevant information to map and allocate memory + */ + stack_frame_allocator(multiboot::memory_information const & mem_info); + + /** + * @brief Allocate memory by finding and returning a free physical frame. + * + * @return next free physical frame or nullopt if none was found. + */ + auto allocate_frame() -> std::optional; + + /** + * @brief Deallocates a previously allocated physical frame. + * + * @param physical_frame Previously allocated physical_frame that should be deallocated. + */ + auto deallocate_frame(physical_frame const & physical_frame) -> void; + + private: + /** + * @brief Load all initally free physical frames from the current memory area into the underlying stack data + * structure so they can simply be accessed once required. Recallling the method will load all free physical frames + * from the next free memory area until there are no memory areas left. + */ + auto load_free_physical_frames() -> void; + + /** + * @brief Find the next memory area and write it into current_area. + */ + auto choose_next_area() -> void; + + stl::stack free_frames; ///< All currently free physical frames in a LIFO (last-in, first-out) + ///< data structure. + physical_frame next_free_frame; ///< The physical_frame after the last allocated one. + std::optional current_area; ///< The current memory area. + multiboot::memory_area_container const + memory_areas; ///< All memory areas in custom container allows to use std::ranges. + physical_frame const kernel_start; ///< The start address of the kernel code in memory. + physical_frame const kernel_end; ///< The end address of the kernel code in memory. + physical_frame const multiboot_start; ///< The start address of the multiboot code in memory. + physical_frame const multiboot_end; ///< The end address of the multiboot code in memory. + }; + +} // namespace teachos::arch::memory::allocator + +#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_STACK_FRAME_ALLOCATOR_HPP diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index dff837e..772f171 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -16,7 +16,7 @@ namespace teachos::arch::memory::heap BUMP, ///< Use the bump allocator as the heap allocation implementation, be aware that using this allocator leaks ///< memory, because there is no delete implementation LINKED_LIST ///< Use the linked list allocator as the heap implementation, recommended because it does not leak - ///< memory and + ///< memory }; /** diff --git a/arch/x86_64/include/arch/stl/stack.hpp b/arch/x86_64/include/arch/stl/stack.hpp new file mode 100644 index 0000000..c78a25e --- /dev/null +++ b/arch/x86_64/include/arch/stl/stack.hpp @@ -0,0 +1,179 @@ +#ifndef TEACHOS_ARCH_X86_64_STL_STACK_HPP +#define TEACHOS_ARCH_X86_64_STL_STACK_HPP + +#include "arch/exception_handling/panic.hpp" +#include "arch/stl/vector.hpp" + +#include +#include + +namespace teachos::arch::stl +{ + /** + * @brief Custom stack implementation mirroring the std::stack to allow for the usage of STL functionality with our + * custom memory management. + * + * @tparam T Element the stack instance should contain. + */ + template> + struct stack + { + /** + * @brief Default Constructor. + */ + stack() = default; + + /** + * @brief Constructs data with the given amount of elements containg the given value or alterantively the default + * constructed value. + * + * @param capacity Amount of elements we want to create and set the given value for. + * @param initial Inital value of all elements in the underlying data array. + */ + explicit stack(std::size_t capacity, T initial = T{}) + : _container(capacity, initial) + { + // Nothing to do. + } + + /** + * @brief Constructs data by copying all element from the given exclusive range. + * + * @tparam InputIterator Template that should have atleast input iterator characteristics. + * @param first Input iterator to the first element in the range we want to copy from. + * @param last Input iterator to one past the last element in the range we want to copy from. + */ + template + explicit stack(InputIterator first, InputIterator last) + : _container(first, last) + { + // Nothing to do. + } + + /** + * @brief Construct data by copying all elements from the initializer list. + * + * @param initalizer_list List we want to copy all elements from. + */ + explicit stack(std::initializer_list initalizer_list) + : _container(initalizer_list) + { + // Nothing to do. + } + + /** + * @brief Copy constructor. + * + * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all + * elements from it. + * + * @param other Other instance of vector we want to copy the data from. + */ + stack(stack const & other) + : _container(other) + { + // Nothing to do. + } + + /** + * @brief Copy assignment operator. + * + * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all + * elements from it. + * + * @param other Other instance of vector we want to copy the data from. + * @return Newly created copy. + */ + stack & operator=(stack const & other) { _container = other; } + + /** + * @brief Destructor. + */ + ~stack() = default; + + /** + * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If + * that is the case the capacity is increased automatically. + * + * @return Current amount of elements. + */ + std::size_t size() const { return _container.size(); } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + T & top() { return _container.back(); } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + T const & top() const { return _container.back(); } + + /** + * @brief Appends the given element value to the end of the container. The new element is initalized as a copy of + * value. + * + * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, + * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. + * Otherwise only the end() iterator is invalidated. + * + * @param value The value of the element to append. + */ + void push(T const & value) { _container.push_back(value); } + + /** + * @brief Appends the given element value to the end of the container. Value is moved into the new element. + * + * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, + * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. + * Otherwise only the end() iterator is invalidated. + * + * @param value The value of the element to append. + */ + void push(T && value) { _container.push_back(std::move(value)); } + + /** + * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the + * template type. The arguments args... are forwarded to the constructor as std::forward(args).... + * + * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case + * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only + * the end() iterator is invalidated. + * + * @tparam Args + * @param args Arguments to forward to the constructor of the element + * @return T& + */ + template + auto emplace(Args &&... args) -> T & + { + _container.emplace_back(std::forward(args)...); + } + + /** + * @brief Removes the last element of the container. Calling pop_back on an empty container results in halting the + * further execution. Iterators and references to the last element are invalidated. The end() + * iterator is also invalidated. + */ + void pop() { _container.pop_back(); } + + /** + * @brief Wheter there are currently any items this container or not. + * + * @return True if there are no elements, false if there are. + */ + auto empty() const -> bool { return _container.empty(); } + + private: + Container _container = {}; ///< Underlying container used by the stack to actually save the data. + }; + +} // namespace teachos::arch::stl + +#endif // TEACHOS_ARCH_X86_64_STL_STACK_HPP diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index f3d41fd..e14f2c9 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -162,13 +162,9 @@ namespace teachos::arch::stl */ void push_back(T const & value) { - if (_size == _capacity) - { - reserve(_capacity * 2); - } - + increase_capacity_if_full(); _data[_size] = value; - _size++; + (void)_size++; } /** @@ -182,11 +178,7 @@ namespace teachos::arch::stl */ void push_back(T && value) { - if (_size == _capacity) - { - reserve(_capacity * 2); - } - + increase_capacity_if_full(); _data[_size] = std::move(value); _size++; } @@ -206,11 +198,7 @@ namespace teachos::arch::stl template auto emplace_back(Args &&... args) -> T & { - if (_size == _capacity) - { - reserve(_capacity * 2); - } - + increase_capacity_if_full(); _data[_size] = T{std::forward(args)...}; auto const index = _size++; return _data[index]; @@ -223,11 +211,8 @@ namespace teachos::arch::stl */ void pop_back() { - if (_size <= 0) - { - exception_handling::panic("[Vector] Attempted to pop back last element of already empty vector"); - } - _size--; + throw_if_empty(); + (void)_size--; } /** @@ -355,7 +340,11 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ - T & front() { return *begin(); } + T & front() + { + throw_if_empty(); + return *begin(); + } /** * @brief Returns a reference to the first element in the container. Calling front on an empty container causes @@ -363,7 +352,11 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ - T const & front() const { return *begin(); } + T const & front() const + { + throw_if_empty(); + return *begin(); + } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -371,7 +364,11 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T & back() { return *rbegin(); } + T & back() + { + throw_if_empty(); + return *rbegin(); + } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -379,7 +376,11 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T const & back() const { return *rbegin(); } + T const & back() const + { + throw_if_empty(); + return *rbegin(); + } /** * @brief Increase the capacity of the vector (the total number of elements that the vector can hold without @@ -442,7 +443,38 @@ namespace teachos::arch::stl _data = temp; } + /** + * @brief Wheter there are currently any items this container or not. + * + * @return True if there are no elements, false if there are. + */ + auto empty() const -> bool { return _size <= 0; } + private: + /** + * @brief Halts the execution of the application if the data container is currently empty. + */ + auto throw_if_empty() const -> void + { + if (empty()) + { + exception_handling::panic("[Vector] Attempted to access element of currently empty vector"); + } + } + + /** + * @brief Increases the internal capacity to 1 if it was previously 0 and to * 2 after that, meaning exponential + * growth. This is done to decrease the amount of single allocations done and because a power of 2 in memory size is + * normally perferable for the cache. + */ + auto increase_capacity_if_full() -> void + { + if (_size == _capacity) + { + reserve(_capacity == 0U ? 1U : _capacity * 2U); + } + } + std::size_t _size = {}; ///< Amount of elements in the underlying data container std::size_t _capacity = {}; ///< Amount of space for elements in the underlying data container T * _data = {}; ///< Pointer to the first element in the underlying data container -- cgit v1.2.3 From 9171b225c7e57db40f949ac4449b37535c46ec94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 15 Apr 2025 10:27:38 +0000 Subject: Adjust comments and readability of stack and vector implementation --- arch/x86_64/include/arch/stl/stack.hpp | 67 ++++++------ arch/x86_64/include/arch/stl/vector.hpp | 174 ++++++++++++++++++-------------- 2 files changed, 136 insertions(+), 105 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/stl/stack.hpp b/arch/x86_64/include/arch/stl/stack.hpp index c78a25e..9ecf0ca 100644 --- a/arch/x86_64/include/arch/stl/stack.hpp +++ b/arch/x86_64/include/arch/stl/stack.hpp @@ -4,9 +4,6 @@ #include "arch/exception_handling/panic.hpp" #include "arch/stl/vector.hpp" -#include -#include - namespace teachos::arch::stl { /** @@ -14,10 +11,18 @@ namespace teachos::arch::stl * custom memory management. * * @tparam T Element the stack instance should contain. + * @tparam Container Actual underlying container that should be wrapped to provide stack functionality. Requires + * access to pop_back(), push_back(), back(), size(), empty() and emplace_back() */ template> struct stack { + using container_type = Container; ///< Type of the underlying container used to implement stack-like interface. + using value_type = Container::value_type; ///< Type of the elements contained in the underlying container. + using size_type = Container::size_type; ///< Type of the size in the underlying container. + using reference = Container::reference; ///< Type of reference to the elements. + using const_reference = Container::const_reference; ///< Type of constant reference to the elements. + /** * @brief Default Constructor. */ @@ -27,11 +32,11 @@ namespace teachos::arch::stl * @brief Constructs data with the given amount of elements containg the given value or alterantively the default * constructed value. * - * @param capacity Amount of elements we want to create and set the given value for. + * @param n Amount of elements we want to create and set the given value for. * @param initial Inital value of all elements in the underlying data array. */ - explicit stack(std::size_t capacity, T initial = T{}) - : _container(capacity, initial) + explicit stack(size_type n, value_type initial = value_type{}) + : _container(n, initial) { // Nothing to do. } @@ -64,10 +69,10 @@ namespace teachos::arch::stl /** * @brief Copy constructor. * - * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all + * @note Allocates underlying data container with the same capacity as stack we are copying from and copies all * elements from it. * - * @param other Other instance of vector we want to copy the data from. + * @param other Other instance of stack we want to copy the data from. */ stack(stack const & other) : _container(other) @@ -97,7 +102,7 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - std::size_t size() const { return _container.size(); } + auto size() const -> size_type { return _container.size(); } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -105,7 +110,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T & top() { return _container.back(); } + auto top() -> reference { return _container.back(); } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -113,30 +118,25 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T const & top() const { return _container.back(); } + auto top() const -> const_reference { return _container.back(); } /** - * @brief Appends the given element value to the end of the container. The new element is initalized as a copy of - * value. + * @brief Appends the given element value to the end of the container. The element is assigned through the + * assignment operator of the template type. The value is forwarded to the constructor as + * std::forward(value), meaning it is either moved (rvalue) or copied (lvalue). * * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. + * Otherwise only the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @param value The value of the element to append. */ - void push(T const & value) { _container.push_back(value); } - - /** - * @brief Appends the given element value to the end of the container. Value is moved into the new element. - * - * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, - * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. - * - * @param value The value of the element to append. - */ - void push(T && value) { _container.push_back(std::move(value)); } + template + auto push(U && value) -> void + { + _container.push_back(std::forward(value)); + } /** * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the @@ -144,24 +144,27 @@ namespace teachos::arch::stl * * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only - * the end() iterator is invalidated. + * the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @tparam Args * @param args Arguments to forward to the constructor of the element - * @return T& + * @return value_type& */ template - auto emplace(Args &&... args) -> T & + auto emplace(Args &&... args) -> reference { _container.emplace_back(std::forward(args)...); } /** - * @brief Removes the last element of the container. Calling pop_back on an empty container results in halting the + * @brief Removes the last element of the container. + * + * @note Calling pop_back on an empty container results in halting the * further execution. Iterators and references to the last element are invalidated. The end() * iterator is also invalidated. */ - void pop() { _container.pop_back(); } + auto pop() -> void { _container.pop_back(); } /** * @brief Wheter there are currently any items this container or not. @@ -171,7 +174,7 @@ namespace teachos::arch::stl auto empty() const -> bool { return _container.empty(); } private: - Container _container = {}; ///< Underlying container used by the stack to actually save the data. + container_type _container = {}; ///< Underlying container used by the stack to actually save the data. }; } // namespace teachos::arch::stl diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index e14f2c9..c7d7853 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -2,9 +2,10 @@ #define TEACHOS_ARCH_X86_64_STL_VECTOR_HPP #include "arch/exception_handling/panic.hpp" +#include "arch/stl/container.hpp" +#include "arch/stl/contiguous_pointer_iterator.hpp" #include -#include namespace teachos::arch::stl { @@ -17,6 +18,13 @@ namespace teachos::arch::stl template struct vector { + using value_type = T; ///< Type of the elements contained in the container. + using size_type = std::size_t; ///< Type of the size in the container. + using reference = value_type &; ///< Type of reference to the elements. + using const_reference = value_type const &; ///< Type of constant reference to the elements. + using pointer = value_type *; ///< Type of pointer to the elements. + using const_pointer = value_type const *; ///< Type of constant pointer to the elements. + /** * @brief Default Constructor. */ @@ -26,15 +34,15 @@ namespace teachos::arch::stl * @brief Constructs data with the given amount of elements containg the given value or alterantively the default * constructed value. * - * @param capacity Amount of elements we want to create and set the given value for. + * @param n Amount of elements we want to create and set the given value for. * @param initial Inital value of all elements in the underlying data array. */ - explicit vector(std::size_t capacity, T initial = T{}) - : _size(capacity) - , _capacity(capacity) - , _data(new T[_capacity]{}) + explicit vector(size_type n, value_type initial = value_type{}) + : _size(n) + , _capacity(n) + , _data(new value_type[_capacity]{}) { - std::ranges::fill(begin(), end(), initial); + std::ranges::fill(*this, initial); } /** @@ -48,9 +56,10 @@ namespace teachos::arch::stl explicit vector(InputIterator first, InputIterator last) : _size(std::distance(first, last)) , _capacity(std::distance(first, last)) - , _data(new T[_capacity]{}) + , _data(new value_type[_capacity]{}) { - std::copy(first, last, _data); + stl::container container{first, last}; + std::ranges::copy(container, _data); } /** @@ -58,12 +67,12 @@ namespace teachos::arch::stl * * @param initalizer_list List we want to copy all elements from. */ - explicit vector(std::initializer_list initalizer_list) + explicit vector(std::initializer_list initalizer_list) : _size(initalizer_list.size()) , _capacity(initalizer_list.size()) - , _data(new T[_capacity]{}) + , _data(new value_type[_capacity]{}) { - std::copy(initalizer_list.begin(), initalizer_list.end(), _data); + std::ranges::copy(initalizer_list, _data); } /** @@ -74,13 +83,13 @@ namespace teachos::arch::stl * * @param other Other instance of vector we want to copy the data from. */ - vector(vector const & other) + vector(vector const & other) : _size(other._size) , _capacity(other._capacity) { delete[] _data; - _data = new T[_capacity]{}; - std::copy(other.begin(), other.end(), _data); + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); } /** @@ -92,13 +101,13 @@ namespace teachos::arch::stl * @param other Other instance of vector we want to copy the data from. * @return Newly created copy. */ - vector & operator=(vector const & other) + vector & operator=(vector const & other) { delete[] _data; _size = other._size; _capacity = other._capacity; - _data = new T[_capacity]{}; - std::copy(other.begin(), other.end(), _data); + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); return *this; } @@ -113,7 +122,7 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - std::size_t size() const { return _size; } + auto size() const -> size_type { return _size; } /** * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we @@ -121,7 +130,17 @@ namespace teachos::arch::stl * * @return Current amount of space the vector has for elements. */ - std::size_t capacity() const { return _capacity; } + auto capacity() const -> size_type { return _capacity; } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Does not do any bounds checks use at() for that. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + auto operator[](size_type index) -> reference { return _data[index]; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -131,7 +150,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & operator[](std::size_t index) { return _data[index]; } + auto operator[](size_type index) const -> const_reference { return _data[index]; } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -141,46 +160,44 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - T & at(std::size_t index) + auto at(size_type index) -> reference { - if (index >= _size) - { - exception_handling::panic("[Vector] Attempted to read element at invalid index"); - } + throw_if_out_of_range(index); return this->operator[](index); } /** - * @brief Appends the given element value to the end of the container. The new element is initalized as a copy of - * value. + * @brief Array indexing operator. Allowing to access element at the given index. * - * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, - * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. + * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. * - * @param value The value of the element to append. + * @param index Index we want to access elements at. + * @return Reference to the underlying element. */ - void push_back(T const & value) + auto at(size_type index) const -> const_reference { - increase_capacity_if_full(); - _data[_size] = value; - (void)_size++; + throw_if_out_of_range(index); + return this->operator[](index); } /** - * @brief Appends the given element value to the end of the container. Value is moved into the new element. + * @brief Appends the given element value to the end of the container. The element is assigned through the + * assignment operator of the template type. The value is forwarded to the constructor as + * std::forward(value), meaning it is either moved (rvalue) or copied (lvalue). * * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. + * Otherwise only the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @param value The value of the element to append. */ - void push_back(T && value) + template + auto push_back(U && value) -> void { increase_capacity_if_full(); - _data[_size] = std::move(value); - _size++; + _data[_size] = std::forward(value); + (void)_size++; } /** @@ -189,17 +206,18 @@ namespace teachos::arch::stl * * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only - * the end() iterator is invalidated. + * the end() iterator is invalidated. Uses a forward reference for the actual value passed, which + * allows the template method to be used by both lvalue and rvalues and compile a different implementation. * * @tparam Args * @param args Arguments to forward to the constructor of the element - * @return T& + * @return value_type& */ template - auto emplace_back(Args &&... args) -> T & + auto emplace_back(Args &&... args) -> value_type & { increase_capacity_if_full(); - _data[_size] = T{std::forward(args)...}; + _data[_size] = value_type{std::forward(args)...}; auto const index = _size++; return _data[index]; } @@ -209,7 +227,7 @@ namespace teachos::arch::stl * further execution. Iterators and references to the last element are invalidated. The end() * iterator is also invalidated. */ - void pop_back() + auto pop_back() -> void { throw_if_empty(); (void)_size--; @@ -221,7 +239,7 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - T * begin() noexcept { return _data; } + auto begin() noexcept -> pointer { return _data; } /** * @brief Returns an iterator to the first element of the vector. @@ -229,7 +247,7 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - T const * begin() const noexcept { return _data; } + auto begin() const noexcept -> const_pointer { return _data; } /** * @brief Returns an iterator to the first element of the vector. @@ -237,7 +255,7 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - T const * cbegin() const noexcept { return begin(); } + auto cbegin() const noexcept -> const_pointer { return begin(); } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -245,7 +263,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - T * rbegin() noexcept { return _data + _size - 1; } + auto rbegin() noexcept -> pointer { return _data + _size - 1; } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -253,7 +271,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - T const * rbegin() const noexcept { return _data + _size - 1; } + auto rbegin() const noexcept -> const_pointer { return _data + _size - 1; } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -261,7 +279,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - T const * crbegin() const noexcept { return rbegin(); } + auto crbegin() const noexcept -> const_pointer { return rbegin(); } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -269,7 +287,7 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - T * end() noexcept { return _data + _size; } + auto end() noexcept -> pointer { return _data + _size; } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -277,7 +295,7 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - T const * end() const noexcept { return _data + _size; } + auto end() const noexcept -> const_pointer { return _data + _size; } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -285,7 +303,7 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - T const * cend() const noexcept { return end(); } + auto cend() const noexcept -> const_pointer { return end(); } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -294,7 +312,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - T * rend() noexcept { return _data + size - 1; } + auto rend() noexcept -> pointer { return _data + size - 1; } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -303,7 +321,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - T const * rend() const noexcept { return _data + size - 1; } + auto rend() const noexcept -> const_pointer { return _data + size - 1; } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -312,7 +330,7 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - T const * crend() const noexcept { return rbegin(); } + auto crend() const noexcept -> const_pointer { return rbegin(); } /** * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range @@ -322,7 +340,7 @@ namespace teachos::arch::stl * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal * to the address of the first element. */ - T * data() { return _data; } + auto data() -> pointer { return _data; } /** * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range @@ -332,7 +350,7 @@ namespace teachos::arch::stl * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal * to the address of the first element. */ - T const * data() const { return _data; } + auto data() const -> const_pointer { return _data; } /** * @brief Returns a reference to the first element in the container. Calling front on an empty container causes @@ -340,7 +358,7 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ - T & front() + auto front() -> reference { throw_if_empty(); return *begin(); @@ -352,7 +370,7 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ - T const & front() const + auto front() const -> const_reference { throw_if_empty(); return *begin(); @@ -364,7 +382,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T & back() + auto back() -> reference { throw_if_empty(); return *rbegin(); @@ -376,7 +394,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - T const & back() const + auto back() const -> const_reference { throw_if_empty(); return *rbegin(); @@ -409,7 +427,7 @@ namespace teachos::arch::stl * * @param new_capacity New capacity of the vector, in number of elements */ - void reserve(std::size_t new_capacity) + auto reserve(size_type new_capacity) -> void { if (new_capacity <= _capacity) { @@ -417,8 +435,9 @@ namespace teachos::arch::stl } _capacity = new_capacity; - T * temp = new T[_capacity]{}; - std::copy(begin(), end(), temp); + value_type * temp = new value_type[_capacity]{}; + stl::container container{begin(), end()}; + std::ranges::copy(container, temp); delete[] _data; _data = temp; } @@ -429,7 +448,7 @@ namespace teachos::arch::stl * If reallocation occurs, all iterators (including the end() iterator) and all references to the elements are * invalidated. If no reallocation occurs, no iterators or references are invalidated. */ - void shrink_to_fit() + auto shrink_to_fit() -> void { if (_size == _capacity) { @@ -437,8 +456,9 @@ namespace teachos::arch::stl } _capacity = _size; - T * temp = new T[_capacity]{}; - std::copy(begin(), end(), temp); + value_type * temp = new value_type[_capacity]{}; + stl::container container{begin(), end()}; + std::copy(container, temp); delete[] _data; _data = temp; } @@ -462,6 +482,14 @@ namespace teachos::arch::stl } } + auto throw_if_out_of_range(size_type index) const -> void + { + if (index >= _size) + { + exception_handling::panic("[Vector] Attempted to read element at invalid index"); + } + } + /** * @brief Increases the internal capacity to 1 if it was previously 0 and to * 2 after that, meaning exponential * growth. This is done to decrease the amount of single allocations done and because a power of 2 in memory size is @@ -475,9 +503,9 @@ namespace teachos::arch::stl } } - std::size_t _size = {}; ///< Amount of elements in the underlying data container - std::size_t _capacity = {}; ///< Amount of space for elements in the underlying data container - T * _data = {}; ///< Pointer to the first element in the underlying data container + size_type _size = {}; ///< Amount of elements in the underlying data container + size_type _capacity = {}; ///< Amount of space for elements in the underlying data container + value_type * _data = {}; ///< Pointer to the first element in the underlying data container }; } // namespace teachos::arch::stl -- cgit v1.2.3 From 8975c5fe091150245fd58a0a42a83b4f41d454e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 15 Apr 2025 13:21:34 +0000 Subject: WIP deque --- arch/x86_64/include/arch/stl/deque.hpp | 524 +++++++++++++++++++++++++++++++++ arch/x86_64/include/arch/stl/stack.hpp | 4 +- 2 files changed, 526 insertions(+), 2 deletions(-) create mode 100644 arch/x86_64/include/arch/stl/deque.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/stl/deque.hpp b/arch/x86_64/include/arch/stl/deque.hpp new file mode 100644 index 0000000..b4a3054 --- /dev/null +++ b/arch/x86_64/include/arch/stl/deque.hpp @@ -0,0 +1,524 @@ +#ifndef TEACHOS_ARCH_X86_64_STL_DEQUE_HPP +#define TEACHOS_ARCH_X86_64_STL_DEQUE_HPP + +#include "arch/exception_handling/panic.hpp" + +#include +#include + +namespace teachos::arch::stl +{ + /** + * @brief Custom deque implementation mirroring the std::deque to allow for the usage of STL functionality with our + * custom memory management. + * + * @tparam T Element the deque instance should contain. + */ + template + struct deque + { + using value_type = T; ///< Type of the elements contained in the container. + using size_type = std::size_t; ///< Type of the size in the container. + using reference = value_type &; ///< Type of reference to the elements. + using const_reference = value_type const &; ///< Type of constant reference to the elements. + using pointer = value_type *; ///< Type of pointer to the elements. + using const_pointer = value_type const *; ///< Type of constant pointer to the elements. + + /** + * @brief Deque block for the linked list, either added or removed if more or less space is required. + */ + struct block + { + std::array data; ///< Data this block in the deque contains + block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. + }; + + /** + * @brief Default Constructor. + */ + deque() = default; + + /** + * @brief Constructs data with the given amount of elements containg the given value or alterantively the default + * constructed value. + * + * @param n Amount of elements we want to create and set the given value for. + * @param initial Inital value of all elements in the underlying data array. + */ + explicit deque(size_type n, value_type initial = value_type{}) + : _size(n) + , _capacity(n) + , _linked_list_start() + { + std::array data{}; + std::ranges::fill_n(data, n, initial); + block block{data, nullptr}; + _linked_list_start = + █ // Taking reference to temporary, how would this be saved without causing issues later? + } + + /** + * @brief Constructs data by copying all element from the given exclusive range. + * + * @tparam InputIterator Template that should have atleast input iterator characteristics. + * @param first Input iterator to the first element in the range we want to copy from. + * @param last Input iterator to one past the last element in the range we want to copy from. + */ + template + explicit deque(InputIterator first, InputIterator last) + : _size(std::distance(first, last)) + , _capacity(std::distance(first, last)) + , _linked_list_start() + { + std::array data{}; + stl::container container{first, last}; + std::ranges::copy(container, data.begin()); + block block{data, nullptr}; + _linked_list_start = █ + } + + /** + * @brief Construct data by copying all elements from the initializer list. + * + * @param initalizer_list List we want to copy all elements from. + */ + explicit deque(std::initializer_list initalizer_list) + : _size(initalizer_list.size()) + , _capacity(initalizer_list.size()) + , _data(new value_type[_capacity]{}) + { + std::ranges::copy(initalizer_list, _data); + } + + /** + * @brief Copy constructor. + * + * @note Allocates underlying data container with the same capacity as deque we are copying from and copies all + * elements from it. + * + * @param other Other instance of deque we want to copy the data from. + */ + deque(deque const & other) + : _size(other._size) + , _capacity(other._capacity) + { + delete[] _data; + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); + } + + /** + * @brief Copy assignment operator. + * + * @note Allocates underlying data container with the same capacity as deque we are copying from and copies all + * elements from it. + * + * @param other Other instance of deque we want to copy the data from. + * @return Newly created copy. + */ + deque & operator=(deque const & other) + { + delete[] _data; + _size = other._size; + _capacity = other._capacity; + _data = new value_type[_capacity]{}; + std::ranges::copy(other, _data); + return *this; + } + + /** + * @brief Destructor. + */ + ~deque() { delete[] _data; } + + /** + * @brief Amount of elements currently contained in this deque, will fill up until we have reached the capacity. If + * that is the case the capacity is increased automatically. + * + * @return Current amount of elements. + */ + auto size() const -> size_type { return _size; } + + /** + * @brief Amount of space the deque currently has, can be different than the size, because we allocate more than we + * exactly require to decrease the amount of allocations and deallocation to improve speed. + * + * @return Current amount of space the deque has for elements. + */ + auto capacity() const -> size_type { return _capacity; } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Does not do any bounds checks use at() for that. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + auto operator[](size_type index) -> reference { return _data[index]; } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Does not do any bounds checks use at() for that. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + auto operator[](size_type index) const -> const_reference { return _data[index]; } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + auto at(size_type index) -> reference + { + throw_if_out_of_range(index); + return this->operator[](index); + } + + /** + * @brief Array indexing operator. Allowing to access element at the given index. + * + * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. + * + * @param index Index we want to access elements at. + * @return Reference to the underlying element. + */ + auto at(size_type index) const -> const_reference + { + throw_if_out_of_range(index); + return this->operator[](index); + } + + /** + * @brief Appends the given element value to the end of the container. Value is moved into the new element. + * + * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, + * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. + * Otherwise only the end() iterator is invalidated. + * + * @param value The value of the element to append. + */ + template + auto push_back(U && value) -> void + { + increase_capacity_if_full(); + _data[_size] = std::forward(value); + (void)_size++; + } + + /** + * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the + * template type. The arguments args... are forwarded to the constructor as std::forward(args).... + * + * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case + * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only + * the end() iterator is invalidated. + * + * @tparam Args + * @param args Arguments to forward to the constructor of the element + * @return value_type& + */ + template + auto emplace_back(Args &&... args) -> value_type & + { + increase_capacity_if_full(); + _data[_size] = value_type{std::forward(args)...}; + auto const index = _size++; + return _data[index]; + } + + /** + * @brief Removes the last element of the container. Calling pop_back on an empty container results in halting the + * further execution. Iterators and references to the last element are invalidated. The end() + * iterator is also invalidated. + */ + auto pop_back() -> void + { + throw_if_empty(); + (void)_size--; + } + + /** + * @brief Returns an iterator to the first element of the deque. + * If the deque is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + auto begin() noexcept -> pointer { return _data; } + + /** + * @brief Returns an iterator to the first element of the deque. + * If the deque is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + auto begin() const noexcept -> const_pointer { return _data; } + + /** + * @brief Returns an iterator to the first element of the deque. + * If the deque is empty, the returned iterator will be equal to end(). + * + * @return Iterator to the first element. + */ + auto cbegin() const noexcept -> const_pointer { return begin(); } + + /** + * @brief Returns a reverse iterator to the first element of the reversed deque. It corresponds to the last element + * of the non-reversed deque. If the deque is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + auto rbegin() noexcept -> pointer { return _data + _size - 1; } + + /** + * @brief Returns a reverse iterator to the first element of the reversed deque. It corresponds to the last element + * of the non-reversed deque. If the deque is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + auto rbegin() const noexcept -> const_pointer { return _data + _size - 1; } + + /** + * @brief Returns a reverse iterator to the first element of the reversed deque. It corresponds to the last element + * of the non-reversed deque. If the deque is empty, the returned iterator will be equal to rend(). + * + * @return Reverse iterator to the first element. + */ + auto crbegin() const noexcept -> const_pointer { return rbegin(); } + + /** + * @brief Returns an iterator to the element following the last element of the deque. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + auto end() noexcept -> pointer { return _data + _size; } + + /** + * @brief Returns an iterator to the element following the last element of the deque. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + auto end() const noexcept -> const_pointer { return _data + _size; } + + /** + * @brief Returns an iterator to the element following the last element of the deque. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Iterator to the element following the last element. + */ + auto cend() const noexcept -> const_pointer { return end(); } + + /** + * @brief Returns a reverse iterator to the element following the last element of the reversed deque. It + * corresponds to the element preceding the first element of the non-reversed deque. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + auto rend() noexcept -> pointer { return _data + size - 1; } + + /** + * @brief Returns a reverse iterator to the element following the last element of the reversed deque. It + * corresponds to the element preceding the first element of the non-reversed deque. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + auto rend() const noexcept -> const_pointer { return _data + size - 1; } + + /** + * @brief Returns a reverse iterator to the element following the last element of the reversed deque. It + * corresponds to the element preceding the first element of the non-reversed deque. This element acts as a + * placeholder, attempting to access it results in undefined behavior. + * + * @return Reverse iterator to the element following the last element. + */ + auto crend() const noexcept -> const_pointer { return rbegin(); } + + /** + * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range + * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable + * in that case). + * + * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal + * to the address of the first element. + */ + auto data() -> pointer { return _data; } + + /** + * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range + * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable + * in that case). + * + * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal + * to the address of the first element. + */ + auto data() const -> const_pointer { return _data; } + + /** + * @brief Returns a reference to the first element in the container. Calling front on an empty container causes + * undefined behavior. + * + * @return Reference to the first element. + */ + auto front() -> reference + { + throw_if_empty(); + return *begin(); + } + + /** + * @brief Returns a reference to the first element in the container. Calling front on an empty container causes + * undefined behavior. + * + * @return Reference to the first element. + */ + auto front() const -> const_reference + { + throw_if_empty(); + return *begin(); + } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + auto back() -> reference + { + throw_if_empty(); + return *rbegin(); + } + + /** + * @brief Returns a reference to the last element in the container. Calling back on an empty container causes + * undefined behavior. + * + * @return Reference to the last element. + */ + auto back() const -> const_reference + { + throw_if_empty(); + return *rbegin(); + } + + /** + * @brief Increase the capacity of the deque (the total number of elements that the deque can hold without + * requiring reallocation) to a value that's greater or equal to new_cap. If new_cap is greater than the current + * capacity(), new storage is allocated, otherwise the function does nothing. + * + * reserve() does not change the size of the deque. + * + * If new_cap is greater than capacity(), all iterators (including the end() iterator) and all references to the + * elements are invalidated. Otherwise, no iterators or references are invalidated. + * + * After a call to reserve(), insertions will not trigger reallocation unless the insertion would make the size of + * the deque greater than the value of capacity(). + * + * @note Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for + * instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing + * the capacity to grow linearly rather than exponentially) and result in increased computational complexity and + * decreased performance. For example, a function that receives an arbitrary deque by reference and appends + * elements to it should usually not call reserve() on the deque, since it does not know of the deque's usage + * characteristics. + * + * When inserting a range, the range version of insert() is generally preferable as it preserves the correct + * capacity growth behavior, unlike reserve() followed by a series of push_back()s. + * + * reserve() cannot be used to reduce the capacity of the container; to that end shrink_to_fit() is provided. + * + * @param new_capacity New capacity of the deque, in number of elements + */ + auto reserve(size_type new_capacity) -> void + { + if (new_capacity <= _capacity) + { + return; + } + + _capacity = new_capacity; + value_type * temp = new value_type[_capacity]{}; + stl::container container{begin(), end()}; + std::ranges::copy(container, temp); + delete[] _data; + _data = temp; + } + + /** + * @brief Requests the removal of unused capacity. Meaning it requests to reduce capacity() to size(). + * + * If reallocation occurs, all iterators (including the end() iterator) and all references to the elements are + * invalidated. If no reallocation occurs, no iterators or references are invalidated. + */ + auto shrink_to_fit() -> void + { + if (_size == _capacity) + { + return; + } + + _capacity = _size; + value_type * temp = new value_type[_capacity]{}; + stl::container container{begin(), end()}; + std::copy(container, temp); + delete[] _data; + _data = temp; + } + + /** + * @brief Wheter there are currently any items this container or not. + * + * @return True if there are no elements, false if there are. + */ + auto empty() const -> bool { return _size <= 0; } + + private: + /** + * @brief Halts the execution of the application if the data container is currently empty. + */ + auto throw_if_empty() const -> void + { + if (empty()) + { + exception_handling::panic("[Deque] Attempted to access element of currently empty deque"); + } + } + + auto throw_if_out_of_range(size_type index) const -> void + { + if (index >= _size) + { + exception_handling::panic("[Deque] Attempted to read element at invalid index"); + } + } + + /** + * @brief Increases the internal capacity to 1 if it was previously 0 and to * 2 after that, meaning exponential + * growth. This is done to decrease the amount of single allocations done and because a power of 2 in memory size is + * normally perferable for the cache. + */ + auto increase_capacity_if_full() -> void + { + if (_size == _capacity) + { + reserve(_capacity == 0U ? 1U : _capacity * 2U); + } + } + + size_type _size = {}; ///< Amount of elements in the underlying data container + size_type _capacity = {}; ///< Amount of space for elements in the underlying data container + block * _linked_list_start = {}; ///< Start pointer to the first element in the linked list + }; + +} // namespace teachos::arch::stl + +#endif // TEACHOS_ARCH_X86_64_STL_DEQUE_HPP diff --git a/arch/x86_64/include/arch/stl/stack.hpp b/arch/x86_64/include/arch/stl/stack.hpp index 9ecf0ca..316aacd 100644 --- a/arch/x86_64/include/arch/stl/stack.hpp +++ b/arch/x86_64/include/arch/stl/stack.hpp @@ -2,7 +2,7 @@ #define TEACHOS_ARCH_X86_64_STL_STACK_HPP #include "arch/exception_handling/panic.hpp" -#include "arch/stl/vector.hpp" +#include "arch/stl/deque.hpp" namespace teachos::arch::stl { @@ -14,7 +14,7 @@ namespace teachos::arch::stl * @tparam Container Actual underlying container that should be wrapped to provide stack functionality. Requires * access to pop_back(), push_back(), back(), size(), empty() and emplace_back() */ - template> + template> struct stack { using container_type = Container; ///< Type of the underlying container used to implement stack-like interface. -- cgit v1.2.3 From 576a7a95b2462ec4938de9fe344657ca04b2ba34 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 17 Apr 2025 14:14:49 +0000 Subject: add syscall interrupt handler --- .../interrupt_handling/generic_interrupt_handler.hpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index 6c1db12..309acbb 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -13,12 +13,12 @@ namespace teachos::arch::interrupt_handling */ struct [[gnu::packed]] interrupt_frame { - uint64_t error_code; ///< Error code pushed by some exceptions. - uint64_t ip; ///< Instruction pointer at the time of the interrupt. - uint64_t cs; ///< Code segment selector indicating privilege level. - uint64_t flags; ///< CPU flags (RFLAGS) storing processor state. - uint64_t sp; ///< Stack pointer at the time of the interrupt. - uint64_t ss; ///< Stack segment selector, usually unused in 64-bit mode. + // uint64_t error_code; ///< Error code pushed by some exceptions. + uint64_t ip; ///< Instruction pointer at the time of the interrupt. + uint64_t cs; ///< Code segment selector indicating privilege level. + uint64_t flags; ///< CPU flags (RFLAGS) storing processor state. + uint64_t sp; ///< Stack pointer at the time of the interrupt. + uint64_t ss; ///< Stack segment selector, usually unused in 64-bit mode. }; /** @@ -29,6 +29,14 @@ namespace teachos::arch::interrupt_handling [[gnu::interrupt]] auto generic_interrupt_handler(struct interrupt_frame * frame) -> void; + /** + * @brief Interrupt handler function for syscalls (INT 0x80). + * + * @param frame Pointer to the interrupt frame containing CPU state. + */ + [[gnu::interrupt]] + auto syscall_interrupt_handler(struct interrupt_frame * frame) -> void; + } // namespace teachos::arch::interrupt_handling #endif // TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP -- cgit v1.2.3 From 5dc0e92a7211b44429c1a2e7efe19c146f5c4f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Apr 2025 10:52:30 +0000 Subject: Remove deque --- arch/x86_64/include/arch/stl/deque.hpp | 524 --------------------------------- arch/x86_64/include/arch/stl/stack.hpp | 4 +- 2 files changed, 2 insertions(+), 526 deletions(-) delete mode 100644 arch/x86_64/include/arch/stl/deque.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/stl/deque.hpp b/arch/x86_64/include/arch/stl/deque.hpp deleted file mode 100644 index b4a3054..0000000 --- a/arch/x86_64/include/arch/stl/deque.hpp +++ /dev/null @@ -1,524 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_STL_DEQUE_HPP -#define TEACHOS_ARCH_X86_64_STL_DEQUE_HPP - -#include "arch/exception_handling/panic.hpp" - -#include -#include - -namespace teachos::arch::stl -{ - /** - * @brief Custom deque implementation mirroring the std::deque to allow for the usage of STL functionality with our - * custom memory management. - * - * @tparam T Element the deque instance should contain. - */ - template - struct deque - { - using value_type = T; ///< Type of the elements contained in the container. - using size_type = std::size_t; ///< Type of the size in the container. - using reference = value_type &; ///< Type of reference to the elements. - using const_reference = value_type const &; ///< Type of constant reference to the elements. - using pointer = value_type *; ///< Type of pointer to the elements. - using const_pointer = value_type const *; ///< Type of constant pointer to the elements. - - /** - * @brief Deque block for the linked list, either added or removed if more or less space is required. - */ - struct block - { - std::array data; ///< Data this block in the deque contains - block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none. - }; - - /** - * @brief Default Constructor. - */ - deque() = default; - - /** - * @brief Constructs data with the given amount of elements containg the given value or alterantively the default - * constructed value. - * - * @param n Amount of elements we want to create and set the given value for. - * @param initial Inital value of all elements in the underlying data array. - */ - explicit deque(size_type n, value_type initial = value_type{}) - : _size(n) - , _capacity(n) - , _linked_list_start() - { - std::array data{}; - std::ranges::fill_n(data, n, initial); - block block{data, nullptr}; - _linked_list_start = - █ // Taking reference to temporary, how would this be saved without causing issues later? - } - - /** - * @brief Constructs data by copying all element from the given exclusive range. - * - * @tparam InputIterator Template that should have atleast input iterator characteristics. - * @param first Input iterator to the first element in the range we want to copy from. - * @param last Input iterator to one past the last element in the range we want to copy from. - */ - template - explicit deque(InputIterator first, InputIterator last) - : _size(std::distance(first, last)) - , _capacity(std::distance(first, last)) - , _linked_list_start() - { - std::array data{}; - stl::container container{first, last}; - std::ranges::copy(container, data.begin()); - block block{data, nullptr}; - _linked_list_start = █ - } - - /** - * @brief Construct data by copying all elements from the initializer list. - * - * @param initalizer_list List we want to copy all elements from. - */ - explicit deque(std::initializer_list initalizer_list) - : _size(initalizer_list.size()) - , _capacity(initalizer_list.size()) - , _data(new value_type[_capacity]{}) - { - std::ranges::copy(initalizer_list, _data); - } - - /** - * @brief Copy constructor. - * - * @note Allocates underlying data container with the same capacity as deque we are copying from and copies all - * elements from it. - * - * @param other Other instance of deque we want to copy the data from. - */ - deque(deque const & other) - : _size(other._size) - , _capacity(other._capacity) - { - delete[] _data; - _data = new value_type[_capacity]{}; - std::ranges::copy(other, _data); - } - - /** - * @brief Copy assignment operator. - * - * @note Allocates underlying data container with the same capacity as deque we are copying from and copies all - * elements from it. - * - * @param other Other instance of deque we want to copy the data from. - * @return Newly created copy. - */ - deque & operator=(deque const & other) - { - delete[] _data; - _size = other._size; - _capacity = other._capacity; - _data = new value_type[_capacity]{}; - std::ranges::copy(other, _data); - return *this; - } - - /** - * @brief Destructor. - */ - ~deque() { delete[] _data; } - - /** - * @brief Amount of elements currently contained in this deque, will fill up until we have reached the capacity. If - * that is the case the capacity is increased automatically. - * - * @return Current amount of elements. - */ - auto size() const -> size_type { return _size; } - - /** - * @brief Amount of space the deque currently has, can be different than the size, because we allocate more than we - * exactly require to decrease the amount of allocations and deallocation to improve speed. - * - * @return Current amount of space the deque has for elements. - */ - auto capacity() const -> size_type { return _capacity; } - - /** - * @brief Array indexing operator. Allowing to access element at the given index. - * - * @note Does not do any bounds checks use at() for that. - * - * @param index Index we want to access elements at. - * @return Reference to the underlying element. - */ - auto operator[](size_type index) -> reference { return _data[index]; } - - /** - * @brief Array indexing operator. Allowing to access element at the given index. - * - * @note Does not do any bounds checks use at() for that. - * - * @param index Index we want to access elements at. - * @return Reference to the underlying element. - */ - auto operator[](size_type index) const -> const_reference { return _data[index]; } - - /** - * @brief Array indexing operator. Allowing to access element at the given index. - * - * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. - * - * @param index Index we want to access elements at. - * @return Reference to the underlying element. - */ - auto at(size_type index) -> reference - { - throw_if_out_of_range(index); - return this->operator[](index); - } - - /** - * @brief Array indexing operator. Allowing to access element at the given index. - * - * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted. - * - * @param index Index we want to access elements at. - * @return Reference to the underlying element. - */ - auto at(size_type index) const -> const_reference - { - throw_if_out_of_range(index); - return this->operator[](index); - } - - /** - * @brief Appends the given element value to the end of the container. Value is moved into the new element. - * - * @note If after the operation the new size() is greater than old capacity() a reallocation takes place, - * in which case all iterators (including the end() iterator) and all references to the elements are invalidated. - * Otherwise only the end() iterator is invalidated. - * - * @param value The value of the element to append. - */ - template - auto push_back(U && value) -> void - { - increase_capacity_if_full(); - _data[_size] = std::forward(value); - (void)_size++; - } - - /** - * @brief Appends a new element to the end of the container. The element is constructed through a constructor of the - * template type. The arguments args... are forwarded to the constructor as std::forward(args).... - * - * If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case - * all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only - * the end() iterator is invalidated. - * - * @tparam Args - * @param args Arguments to forward to the constructor of the element - * @return value_type& - */ - template - auto emplace_back(Args &&... args) -> value_type & - { - increase_capacity_if_full(); - _data[_size] = value_type{std::forward(args)...}; - auto const index = _size++; - return _data[index]; - } - - /** - * @brief Removes the last element of the container. Calling pop_back on an empty container results in halting the - * further execution. Iterators and references to the last element are invalidated. The end() - * iterator is also invalidated. - */ - auto pop_back() -> void - { - throw_if_empty(); - (void)_size--; - } - - /** - * @brief Returns an iterator to the first element of the deque. - * If the deque is empty, the returned iterator will be equal to end(). - * - * @return Iterator to the first element. - */ - auto begin() noexcept -> pointer { return _data; } - - /** - * @brief Returns an iterator to the first element of the deque. - * If the deque is empty, the returned iterator will be equal to end(). - * - * @return Iterator to the first element. - */ - auto begin() const noexcept -> const_pointer { return _data; } - - /** - * @brief Returns an iterator to the first element of the deque. - * If the deque is empty, the returned iterator will be equal to end(). - * - * @return Iterator to the first element. - */ - auto cbegin() const noexcept -> const_pointer { return begin(); } - - /** - * @brief Returns a reverse iterator to the first element of the reversed deque. It corresponds to the last element - * of the non-reversed deque. If the deque is empty, the returned iterator will be equal to rend(). - * - * @return Reverse iterator to the first element. - */ - auto rbegin() noexcept -> pointer { return _data + _size - 1; } - - /** - * @brief Returns a reverse iterator to the first element of the reversed deque. It corresponds to the last element - * of the non-reversed deque. If the deque is empty, the returned iterator will be equal to rend(). - * - * @return Reverse iterator to the first element. - */ - auto rbegin() const noexcept -> const_pointer { return _data + _size - 1; } - - /** - * @brief Returns a reverse iterator to the first element of the reversed deque. It corresponds to the last element - * of the non-reversed deque. If the deque is empty, the returned iterator will be equal to rend(). - * - * @return Reverse iterator to the first element. - */ - auto crbegin() const noexcept -> const_pointer { return rbegin(); } - - /** - * @brief Returns an iterator to the element following the last element of the deque. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Iterator to the element following the last element. - */ - auto end() noexcept -> pointer { return _data + _size; } - - /** - * @brief Returns an iterator to the element following the last element of the deque. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Iterator to the element following the last element. - */ - auto end() const noexcept -> const_pointer { return _data + _size; } - - /** - * @brief Returns an iterator to the element following the last element of the deque. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Iterator to the element following the last element. - */ - auto cend() const noexcept -> const_pointer { return end(); } - - /** - * @brief Returns a reverse iterator to the element following the last element of the reversed deque. It - * corresponds to the element preceding the first element of the non-reversed deque. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Reverse iterator to the element following the last element. - */ - auto rend() noexcept -> pointer { return _data + size - 1; } - - /** - * @brief Returns a reverse iterator to the element following the last element of the reversed deque. It - * corresponds to the element preceding the first element of the non-reversed deque. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Reverse iterator to the element following the last element. - */ - auto rend() const noexcept -> const_pointer { return _data + size - 1; } - - /** - * @brief Returns a reverse iterator to the element following the last element of the reversed deque. It - * corresponds to the element preceding the first element of the non-reversed deque. This element acts as a - * placeholder, attempting to access it results in undefined behavior. - * - * @return Reverse iterator to the element following the last element. - */ - auto crend() const noexcept -> const_pointer { return rbegin(); } - - /** - * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range - * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable - * in that case). - * - * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal - * to the address of the first element. - */ - auto data() -> pointer { return _data; } - - /** - * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range - * [data(), data() + size()) is always a valid range, even if the container is empty (data() is not dereferenceable - * in that case). - * - * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal - * to the address of the first element. - */ - auto data() const -> const_pointer { return _data; } - - /** - * @brief Returns a reference to the first element in the container. Calling front on an empty container causes - * undefined behavior. - * - * @return Reference to the first element. - */ - auto front() -> reference - { - throw_if_empty(); - return *begin(); - } - - /** - * @brief Returns a reference to the first element in the container. Calling front on an empty container causes - * undefined behavior. - * - * @return Reference to the first element. - */ - auto front() const -> const_reference - { - throw_if_empty(); - return *begin(); - } - - /** - * @brief Returns a reference to the last element in the container. Calling back on an empty container causes - * undefined behavior. - * - * @return Reference to the last element. - */ - auto back() -> reference - { - throw_if_empty(); - return *rbegin(); - } - - /** - * @brief Returns a reference to the last element in the container. Calling back on an empty container causes - * undefined behavior. - * - * @return Reference to the last element. - */ - auto back() const -> const_reference - { - throw_if_empty(); - return *rbegin(); - } - - /** - * @brief Increase the capacity of the deque (the total number of elements that the deque can hold without - * requiring reallocation) to a value that's greater or equal to new_cap. If new_cap is greater than the current - * capacity(), new storage is allocated, otherwise the function does nothing. - * - * reserve() does not change the size of the deque. - * - * If new_cap is greater than capacity(), all iterators (including the end() iterator) and all references to the - * elements are invalidated. Otherwise, no iterators or references are invalidated. - * - * After a call to reserve(), insertions will not trigger reallocation unless the insertion would make the size of - * the deque greater than the value of capacity(). - * - * @note Correctly using reserve() can prevent unnecessary reallocations, but inappropriate uses of reserve() (for - * instance, calling it before every push_back() call) may actually increase the number of reallocations (by causing - * the capacity to grow linearly rather than exponentially) and result in increased computational complexity and - * decreased performance. For example, a function that receives an arbitrary deque by reference and appends - * elements to it should usually not call reserve() on the deque, since it does not know of the deque's usage - * characteristics. - * - * When inserting a range, the range version of insert() is generally preferable as it preserves the correct - * capacity growth behavior, unlike reserve() followed by a series of push_back()s. - * - * reserve() cannot be used to reduce the capacity of the container; to that end shrink_to_fit() is provided. - * - * @param new_capacity New capacity of the deque, in number of elements - */ - auto reserve(size_type new_capacity) -> void - { - if (new_capacity <= _capacity) - { - return; - } - - _capacity = new_capacity; - value_type * temp = new value_type[_capacity]{}; - stl::container container{begin(), end()}; - std::ranges::copy(container, temp); - delete[] _data; - _data = temp; - } - - /** - * @brief Requests the removal of unused capacity. Meaning it requests to reduce capacity() to size(). - * - * If reallocation occurs, all iterators (including the end() iterator) and all references to the elements are - * invalidated. If no reallocation occurs, no iterators or references are invalidated. - */ - auto shrink_to_fit() -> void - { - if (_size == _capacity) - { - return; - } - - _capacity = _size; - value_type * temp = new value_type[_capacity]{}; - stl::container container{begin(), end()}; - std::copy(container, temp); - delete[] _data; - _data = temp; - } - - /** - * @brief Wheter there are currently any items this container or not. - * - * @return True if there are no elements, false if there are. - */ - auto empty() const -> bool { return _size <= 0; } - - private: - /** - * @brief Halts the execution of the application if the data container is currently empty. - */ - auto throw_if_empty() const -> void - { - if (empty()) - { - exception_handling::panic("[Deque] Attempted to access element of currently empty deque"); - } - } - - auto throw_if_out_of_range(size_type index) const -> void - { - if (index >= _size) - { - exception_handling::panic("[Deque] Attempted to read element at invalid index"); - } - } - - /** - * @brief Increases the internal capacity to 1 if it was previously 0 and to * 2 after that, meaning exponential - * growth. This is done to decrease the amount of single allocations done and because a power of 2 in memory size is - * normally perferable for the cache. - */ - auto increase_capacity_if_full() -> void - { - if (_size == _capacity) - { - reserve(_capacity == 0U ? 1U : _capacity * 2U); - } - } - - size_type _size = {}; ///< Amount of elements in the underlying data container - size_type _capacity = {}; ///< Amount of space for elements in the underlying data container - block * _linked_list_start = {}; ///< Start pointer to the first element in the linked list - }; - -} // namespace teachos::arch::stl - -#endif // TEACHOS_ARCH_X86_64_STL_DEQUE_HPP diff --git a/arch/x86_64/include/arch/stl/stack.hpp b/arch/x86_64/include/arch/stl/stack.hpp index 316aacd..9ecf0ca 100644 --- a/arch/x86_64/include/arch/stl/stack.hpp +++ b/arch/x86_64/include/arch/stl/stack.hpp @@ -2,7 +2,7 @@ #define TEACHOS_ARCH_X86_64_STL_STACK_HPP #include "arch/exception_handling/panic.hpp" -#include "arch/stl/deque.hpp" +#include "arch/stl/vector.hpp" namespace teachos::arch::stl { @@ -14,7 +14,7 @@ namespace teachos::arch::stl * @tparam Container Actual underlying container that should be wrapped to provide stack functionality. Requires * access to pop_back(), push_back(), back(), size(), empty() and emplace_back() */ - template> + template> struct stack { using container_type = Container; ///< Type of the underlying container used to implement stack-like interface. -- cgit v1.2.3 From 5f149faeb9d41bb56733075b0e56908b3731d38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Apr 2025 09:32:59 +0000 Subject: Move gnu function attributes to header file --- .../include/arch/interrupt_handling/generic_interrupt_handler.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index 309acbb..9530a77 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -26,7 +26,7 @@ namespace teachos::arch::interrupt_handling * * @param frame Pointer to the interrupt frame containing CPU state. */ - [[gnu::interrupt]] + [[gnu::interrupt]] [[gnu::section(".interrupt_text")]] auto generic_interrupt_handler(struct interrupt_frame * frame) -> void; /** @@ -34,7 +34,7 @@ namespace teachos::arch::interrupt_handling * * @param frame Pointer to the interrupt frame containing CPU state. */ - [[gnu::interrupt]] + [[gnu::interrupt]] [[gnu::section(".interrupt_text")]] auto syscall_interrupt_handler(struct interrupt_frame * frame) -> void; } // namespace teachos::arch::interrupt_handling -- cgit v1.2.3 From c865eff02ae1978b4f665432d853374d1ffacecf Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Apr 2025 10:21:29 +0000 Subject: create trampoline for syscall --- arch/x86_64/include/arch/boot/pointers.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index fe9c657..d9a7ab7 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -10,6 +10,8 @@ namespace teachos::arch::boot */ extern "C" size_t const multiboot_information_pointer; + extern "C" void syscall_trampoline(); + } // namespace teachos::arch::boot #endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP -- cgit v1.2.3 From 7261c64bb236a313ed8846a9c9dbded6890a9e98 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 27 Apr 2025 11:20:02 +0000 Subject: wip implement syscall in cpp --- arch/x86_64/include/arch/boot/pointers.hpp | 2 -- arch/x86_64/include/arch/context_switching/main.hpp | 2 ++ arch/x86_64/include/arch/context_switching/syscall_handler.hpp | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/syscall_handler.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index d9a7ab7..fe9c657 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -10,8 +10,6 @@ namespace teachos::arch::boot */ extern "C" size_t const multiboot_information_pointer; - extern "C" void syscall_trampoline(); - } // namespace teachos::arch::boot #endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp index f8477ea..5537174 100644 --- a/arch/x86_64/include/arch/context_switching/main.hpp +++ b/arch/x86_64/include/arch/context_switching/main.hpp @@ -46,6 +46,8 @@ namespace teachos::arch::context_switching auto switch_context(interrupt_descriptor_table::segment_selector data_segment, interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void; + auto setup_syscall() -> void; + } // namespace teachos::arch::context_switching #endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP diff --git a/arch/x86_64/include/arch/context_switching/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall_handler.hpp new file mode 100644 index 0000000..8583051 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/syscall_handler.hpp @@ -0,0 +1,8 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_HANDLER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_HANDLER_HPP + +namespace teachos::arch::context_switching +{ + auto syscall_handler() -> void; +} +#endif \ No newline at end of file -- cgit v1.2.3 From 187eba4eca3ea46d8c26419168e525242338dae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Apr 2025 13:18:49 +0000 Subject: Simplify syscall setup --- arch/x86_64/include/arch/context_switching/syscall_handler.hpp | 1 + arch/x86_64/include/arch/kernel/cpu/segment_register.hpp | 1 + 2 files changed, 2 insertions(+) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall_handler.hpp index 8583051..5a46924 100644 --- a/arch/x86_64/include/arch/context_switching/syscall_handler.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall_handler.hpp @@ -3,6 +3,7 @@ namespace teachos::arch::context_switching { + [[gnu::naked]] auto syscall_handler() -> void; } #endif \ No newline at end of file diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp index 6a2ca3e..36ada23 100644 --- a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -86,6 +86,7 @@ namespace teachos::arch::kernel::cpu * @param code_segment Code Segment that should be loaded into the CS register. * @param address Function that we want to call in the new context created by the given Code Segment. */ + [[gnu::naked]] auto set_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector data_segment, context_switching::interrupt_descriptor_table::segment_selector code_segment, uint64_t address) -> void; -- cgit v1.2.3 From 13dd2bd5a88ec7efeadf8586778f2c5a26d8cd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 27 Apr 2025 14:07:33 +0000 Subject: Move not public methods into anonymous namespace --- .../interrupt_descriptor_table/segment_selector.hpp | 7 +++++++ arch/x86_64/include/arch/context_switching/main.hpp | 2 -- arch/x86_64/include/arch/context_switching/syscall_handler.hpp | 9 --------- 3 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 arch/x86_64/include/arch/context_switching/syscall_handler.hpp (limited to 'arch/x86_64/include') 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 e8854f9..7bfb563 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 @@ -82,6 +82,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ auto operator|=(std::bitset<3U> other) -> void; + /** + * @brief Combines all bits in the underlying data in the correct order to return a raw value containing all bits. + * + * @return Underlying value combined into it's full size. + */ + operator uint16_t() const { return static_cast(_flags) | (static_cast(_index) << 3U); } + private: uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from. uint16_t _index : 13 = diff --git a/arch/x86_64/include/arch/context_switching/main.hpp b/arch/x86_64/include/arch/context_switching/main.hpp index 5537174..f8477ea 100644 --- a/arch/x86_64/include/arch/context_switching/main.hpp +++ b/arch/x86_64/include/arch/context_switching/main.hpp @@ -46,8 +46,6 @@ namespace teachos::arch::context_switching auto switch_context(interrupt_descriptor_table::segment_selector data_segment, interrupt_descriptor_table::segment_selector code_segment, void (*return_function)()) -> void; - auto setup_syscall() -> void; - } // namespace teachos::arch::context_switching #endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_MAIN_HPP diff --git a/arch/x86_64/include/arch/context_switching/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall_handler.hpp deleted file mode 100644 index 5a46924..0000000 --- a/arch/x86_64/include/arch/context_switching/syscall_handler.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_HANDLER_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_HANDLER_HPP - -namespace teachos::arch::context_switching -{ - [[gnu::naked]] - auto syscall_handler() -> void; -} -#endif \ No newline at end of file -- cgit v1.2.3 From 151b699058d994c0aee18cc17fe56aecc15ea336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 28 Apr 2025 14:45:54 +0000 Subject: Remove duplicate struct --- .../include/arch/interrupt_handling/generic_interrupt_handler.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index 9530a77..866d15d 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -27,7 +27,7 @@ namespace teachos::arch::interrupt_handling * @param frame Pointer to the interrupt frame containing CPU state. */ [[gnu::interrupt]] [[gnu::section(".interrupt_text")]] - auto generic_interrupt_handler(struct interrupt_frame * frame) -> void; + auto generic_interrupt_handler(interrupt_frame * frame) -> void; /** * @brief Interrupt handler function for syscalls (INT 0x80). @@ -35,7 +35,7 @@ namespace teachos::arch::interrupt_handling * @param frame Pointer to the interrupt frame containing CPU state. */ [[gnu::interrupt]] [[gnu::section(".interrupt_text")]] - auto syscall_interrupt_handler(struct interrupt_frame * frame) -> void; + auto syscall_interrupt_handler(interrupt_frame * frame) -> void; } // namespace teachos::arch::interrupt_handling -- cgit v1.2.3 From 7c045d8ded72017ff11fd4b9b02148987b944caf Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 1 May 2025 12:25:40 +0000 Subject: WIP experiment with converting GDT to 8-Byte entries --- .../segment_selector.hpp | 8 ++--- .../global_descriptor_table.hpp | 6 ++-- .../global_descriptor_table_pointer.hpp | 18 +++++++++--- .../segment_descriptor.hpp | 12 ++++++++ .../segment_descriptor_base.hpp | 34 ++++++++++++++++++++++ .../segment_descriptor_extension.hpp | 31 ++++++++++++++++++++ 6 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp create mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp (limited to 'arch/x86_64/include') 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 7bfb563..8748448 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 @@ -44,17 +44,13 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table * @brief Constructor. * * @param index Index into the local or global descriptor table. Processor multiplies the index value by 8 (number - * of bytes in 32-bit segment descriptor) and adds the result to the base GDT or LDT address. Because it only - * multiplies by 8, but we are using long mode the constructor additionally multiplies the given value by two. This - * is done because 64-bit segment descriptor are twice as big in size. If we wouldn't multiply by two, index 1 would - * result in the middle between the second part of the null entry and the first part of the code kernel segment and - * therefore be invalid. + * of bytes in 32-bit segment descriptor) and adds the result to the base GDT or LDT 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. */ constexpr segment_selector(uint16_t index, uint8_t flags) : _flags(flags) - , _index(index * 2U) + , _index(index) { // Nothing to do. } diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp index bd69a46..84a24a2 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp @@ -12,7 +12,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table * * @return Reference to the created global_descriptor_table. */ - auto get_or_create_global_descriptor_table() -> global_descriptor_table &; + auto get_or_create_gdt() -> global_descriptor_table &; /** * @brief Updates the GDTR with the created global descriptor table. If it has not been created yet this @@ -21,13 +21,13 @@ namespace teachos::arch::context_switching::segment_descriptor_table * @note This method will only set the GDTR, but for the processor to actually register the change a far jump * has to be executed. This also has to be done before updating the TR. */ - auto update_global_descriptor_table_register() -> void; + auto update_gdtr() -> void; /** * @brief Updates the TR with the created task state segment. If it has not been created yet this * method will create it. * - * @note This method should only be called after update_global_descriptor_table_register() and a far jump has been + * @note This method should only be called after update_gdtr() and a far jump has been * executed. Because before that trying to access the segment will cause an exception. */ auto update_task_state_segment_register() -> void; diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp index 6fac2a0..c54647d 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp @@ -1,14 +1,24 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP -#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" +#include "arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp" +#include "arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp" #include "arch/stl/vector.hpp" #include namespace teachos::arch::context_switching::segment_descriptor_table { - using global_descriptor_table = stl::vector; + struct __attribute__((packed, aligned(8))) global_descriptor_table + { + segment_descriptor_base null; + segment_descriptor_base kernel_code; + segment_descriptor_base kernel_data; + segment_descriptor_base user_code; + segment_descriptor_base user_data; + segment_descriptor_base tss_low; + segment_descriptor_extension tss_high; + }; /** * @brief Represents a pointer to the Global Descriptor Table (GDT). @@ -26,7 +36,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table /** * @brief Constructor. */ - global_descriptor_table_pointer(uint16_t table_length, segment_descriptor * address); + global_descriptor_table_pointer(uint16_t table_length, seg_desc * address); /** * @brief Defaulted three-way comparsion operator. @@ -35,7 +45,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table private: uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. - segment_descriptor * address = {}; ///< Non-owning pointer to the GDT base address. + seg_desc * address = {}; ///< Non-owning pointer to the GDT base address. }; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp index 7fe4ecb..ccd604d 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp @@ -10,6 +10,12 @@ namespace teachos::arch::context_switching::segment_descriptor_table __extension__ typedef __int128 int128_t; __extension__ typedef unsigned __int128 uint128_t; + struct seg_desc + { + private: + uint64_t : 64; ///< Makes sure the struct is 8-Bytes big + }; + /** * @brief Defines helper function for all states and the actual data the segment descriptor can have. */ @@ -44,6 +50,12 @@ namespace teachos::arch::context_switching::segment_descriptor_table */ segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit); + auto get_limit_1() -> uint16_t; + auto get_base_1() -> uint32_t; + auto get_access() -> access_byte; + auto get_flag() -> gdt_flags; + auto get_base_2() -> uint64_t; + /** * @brief Calculates the underlying segment type that this segement descriptor is describing. */ diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp new file mode 100644 index 0000000..18c9da1 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp @@ -0,0 +1,34 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_BASE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_BASE_HPP + +#include "arch/context_switching/segment_descriptor_table/access_byte.hpp" +#include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp" +#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" +#include "arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp" + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + /** + * @brief Defines helper function for all states and the actual data the segment descriptor can have. + */ + struct [[gnu::packed]] segment_descriptor_base : seg_desc + { + /** + * @brief Default Constructor. + */ + segment_descriptor_base() = default; + + /** + * @brief Constructor. + */ + segment_descriptor_base(segment_descriptor segment_descriptor); + + private: + uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) + uint32_t _base_1 : 24 = {}; ///< First part of the base field (16 - 39) + access_byte _access = {}; ///< Access byte field (40 - 47) + gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55) + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_BASE_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp new file mode 100644 index 0000000..0b724f2 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp @@ -0,0 +1,31 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP + +#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" + +#include + +namespace teachos::arch::context_switching::segment_descriptor_table +{ + /** + * @brief Defines helper function for all states and the actual data the segment descriptor can have. + */ + struct [[gnu::packed]] segment_descriptor_extension : seg_desc + { + /** + * @brief Default Constructor. + */ + segment_descriptor_extension() = default; + + /** + * @brief Constructor. + */ + segment_descriptor_extension(segment_descriptor segment_descriptor); + + private: + uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) + uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) + }; +} // namespace teachos::arch::context_switching::segment_descriptor_table + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP -- cgit v1.2.3 From 099a7fbbc35a71f98553fa39899f2d17c555242f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 2 May 2025 14:49:06 +0000 Subject: Finish implementing 8-byte GDT entries and syscall arg loads. --- .../segment_selector.hpp | 4 +- .../global_descriptor_table.hpp | 2 +- .../global_descriptor_table_pointer.hpp | 17 +---- .../segment_descriptor.hpp | 83 ---------------------- .../segment_descriptor_base.hpp | 45 +++++++++++- .../segment_descriptor_extension.hpp | 57 +++++++++++++-- 6 files changed, 98 insertions(+), 110 deletions(-) delete mode 100644 arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp (limited to 'arch/x86_64/include') 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 8748448..5be449f 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 @@ -79,11 +79,11 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table auto operator|=(std::bitset<3U> other) -> void; /** - * @brief Combines all bits in the underlying data in the correct order to return a raw value containing all bits. + * @brief Cast the underlying data into a combined 16-bit form, that contains all data. * * @return Underlying value combined into it's full size. */ - operator uint16_t() const { return static_cast(_flags) | (static_cast(_index) << 3U); } + operator uint16_t() const; private: uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from. diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp index 84a24a2..44f2692 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp @@ -30,7 +30,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table * @note This method should only be called after update_gdtr() and a far jump has been * executed. Because before that trying to access the segment will cause an exception. */ - auto update_task_state_segment_register() -> void; + auto update_tss_register() -> void; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp index c54647d..292ff70 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp @@ -1,24 +1,13 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_GLOBAL_DESCRIPTOR_TABLE_POINTER_HPP -#include "arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp" -#include "arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp" #include "arch/stl/vector.hpp" #include namespace teachos::arch::context_switching::segment_descriptor_table { - struct __attribute__((packed, aligned(8))) global_descriptor_table - { - segment_descriptor_base null; - segment_descriptor_base kernel_code; - segment_descriptor_base kernel_data; - segment_descriptor_base user_code; - segment_descriptor_base user_data; - segment_descriptor_base tss_low; - segment_descriptor_extension tss_high; - }; + using global_descriptor_table = stl::vector; /** * @brief Represents a pointer to the Global Descriptor Table (GDT). @@ -36,7 +25,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table /** * @brief Constructor. */ - global_descriptor_table_pointer(uint16_t table_length, seg_desc * address); + global_descriptor_table_pointer(uint16_t table_length, uint64_t * address); /** * @brief Defaulted three-way comparsion operator. @@ -45,7 +34,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table private: uint16_t table_length = {}; ///< The amount of segment descriptor entries in the global descriptor table - 1. - seg_desc * address = {}; ///< Non-owning pointer to the GDT base address. + uint64_t * address = {}; ///< Non-owning pointer to the GDT base address. }; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp deleted file mode 100644 index ccd604d..0000000 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP -#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP - -#include "arch/context_switching/segment_descriptor_table/access_byte.hpp" -#include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp" -#include "arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp" - -namespace teachos::arch::context_switching::segment_descriptor_table -{ - __extension__ typedef __int128 int128_t; - __extension__ typedef unsigned __int128 uint128_t; - - struct seg_desc - { - private: - uint64_t : 64; ///< Makes sure the struct is 8-Bytes big - }; - - /** - * @brief Defines helper function for all states and the actual data the segment descriptor can have. - */ - struct [[gnu::packed]] segment_descriptor - { - /** - * @brief Default Constructor. - */ - segment_descriptor() = default; - - /** - * @brief Constructor. - * - * @note Created segment descriptor copies the given bytes into theese components ending with a 32 bit reserved - * field that has to be used, because the 64-bit segment descriptor needs to be big enough for two 32-bit segment - * descriptor. - * - 8 bit Access Type - * - 4 bit Flags - * - 64 bit Base Address - * - 20 bit Limit - * - * @param flags Copies the bits set from the given data into the individual components of a segment - * descriptor. - */ - explicit segment_descriptor(uint128_t flags); - - /** - * @brief Constructor. - * - * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of - * a segment descriptor. - */ - segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit); - - auto get_limit_1() -> uint16_t; - auto get_base_1() -> uint32_t; - auto get_access() -> access_byte; - auto get_flag() -> gdt_flags; - auto get_base_2() -> uint64_t; - - /** - * @brief Calculates the underlying segment type that this segement descriptor is describing. - */ - auto get_segment_type() const -> segment_descriptor_type; - - /** - * @brief Allows to compare the underlying bits of two instances. - * - * @param other Other instance that we want to compare with. - * @return Whether the underlying set bits of both types are the same. - */ - auto operator==(segment_descriptor const & other) const -> bool = default; - - private: - // The order in private variables starts for the first variable being the rightmost bit. - uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) - uint32_t _base_1 : 24 = {}; ///< First part of the base field (16 - 39) - access_byte _access = {}; ///< Access byte field (40 - 47) - gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55) - uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) - uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) - }; -} // namespace teachos::arch::context_switching::segment_descriptor_table - -#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_HPP diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp index 18c9da1..933fb4d 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp @@ -3,7 +3,6 @@ #include "arch/context_switching/segment_descriptor_table/access_byte.hpp" #include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp" -#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" #include "arch/context_switching/segment_descriptor_table/segment_descriptor_type.hpp" namespace teachos::arch::context_switching::segment_descriptor_table @@ -11,7 +10,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table /** * @brief Defines helper function for all states and the actual data the segment descriptor can have. */ - struct [[gnu::packed]] segment_descriptor_base : seg_desc + struct [[gnu::packed]] segment_descriptor_base { /** * @brief Default Constructor. @@ -20,14 +19,54 @@ namespace teachos::arch::context_switching::segment_descriptor_table /** * @brief Constructor. + * + * @note Created segment descriptor copies the given bytes into these components requiring the space of one + * segment descriptor entry in the global descriptor table being 64-bit. + * - 8 bit Access Type + * - 4 bit Flags + * - 32 bit Base Address + * - 20 bit Limit + * + * @param flags Copies the bits set from the given data into the individual components of a segment + * descriptor. */ - segment_descriptor_base(segment_descriptor segment_descriptor); + explicit segment_descriptor_base(uint64_t flags); + + /** + * @brief Constructor. + * + * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of + * a segment descriptor. + */ + segment_descriptor_base(access_byte access_byte, gdt_flags flags, uint32_t base, std::bitset<20U> limit); + + /** + * @brief Calculates the underlying segment type that this segement descriptor is describing. + */ + auto get_segment_type() const -> segment_descriptor_type; + + /** + * @brief Cast the underlying data into a combined 64-bit form, that contains all data. + * + * @return Underlying value combined into it's full size. + */ + operator uint64_t() const; + + /** + * @brief Allows to compare the underlying bits of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying set bits of both types are the same. + */ + auto operator==(segment_descriptor_base const & other) const -> bool = default; private: + // The order in private variables starts for the first variable being the rightmost bit. uint16_t _limit_1 = {}; ///< First part of the limit field (0 - 15) uint32_t _base_1 : 24 = {}; ///< First part of the base field (16 - 39) access_byte _access = {}; ///< Access byte field (40 - 47) gdt_flags _flag = {}; ///< Second part of the limit field + Flags field (48 - 55) + uint8_t _base_2 = {}; ///< Second part of the base field (56 - 63) }; } // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp index 0b724f2..40bcc8a 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp @@ -1,16 +1,17 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SEGMENT_DESCRIPTOR_TABLE_SEGMENT_DESCRIPTOR_EXTENSION_HPP -#include "arch/context_switching/segment_descriptor_table/segment_descriptor.hpp" - -#include +#include "arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp" namespace teachos::arch::context_switching::segment_descriptor_table { + __extension__ typedef __int128 int128_t; + __extension__ typedef unsigned __int128 uint128_t; + /** * @brief Defines helper function for all states and the actual data the segment descriptor can have. */ - struct [[gnu::packed]] segment_descriptor_extension : seg_desc + struct [[gnu::packed]] segment_descriptor_extension { /** * @brief Default Constructor. @@ -19,12 +20,54 @@ namespace teachos::arch::context_switching::segment_descriptor_table /** * @brief Constructor. + * + * @note Created segment descriptor copies the given bytes into these components requiring the space of two + * segment descriptor entry in the global descriptor table being 128-bit. Ending with a 32 bit reserved + * field that has to be used, because the segment descriptor needs to be big enough for two segment + * descriptor entries. + * - 8 bit Access Type + * - 4 bit Flags + * - 64 bit Base Address + * - 20 bit Limit + * + * @param flags Copies the bits set from the given data into the individual components of a segment + * descriptor. + */ + explicit segment_descriptor_extension(uint128_t flags); + + /** + * @brief Constructor. + * + * @param access_byte, flags, base, limit Copies the bits set from the given data into the individual components of + * a segment descriptor. + */ + segment_descriptor_extension(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit); + + /** + * @brief Returns the underlying base segment descriptor, being the first part of the segment descriptor consisting + * of two entries in the global descriptor table. + */ + auto get_first_gdt_entry() const -> segment_descriptor_base; + + /** + * @brief Returns the underlying extension to the segment descriptor, being the second part of the segment + * descriptor consiting of two entries in the global descriptor table. + */ + auto get_second_gdt_entry() const -> uint64_t; + + /** + * @brief Allows to compare the underlying bits of two instances. + * + * @param other Other instance that we want to compare with. + * @return Whether the underlying set bits of both types are the same. */ - segment_descriptor_extension(segment_descriptor segment_descriptor); + auto operator==(segment_descriptor_extension const & other) const -> bool = default; private: - uint64_t _base_2 : 40 = {}; ///< Second part of the base field (56 - 95) - uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) + // The order in private variables starts for the first variable being the rightmost bit. + segment_descriptor_base _base = {}; ///< Base Segment Descriptor representing single entry in GDT (0 - 63) + uint32_t _base_3 = {}; ///< Third part of the base field (63 - 95) + uint32_t : 32; ///< Reserved field used to ensure this struct is 128 bits big (96 - 127) }; } // namespace teachos::arch::context_switching::segment_descriptor_table -- cgit v1.2.3 From 5a8c9d2f2e4a3d2810f81c35070c6ef0926cfdd1 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 3 May 2025 09:45:45 +0000 Subject: write wrapper function for syscall --- .../arch/context_switching/syscall/main.hpp | 28 ++++++++++++++++++++++ .../context_switching/syscall/syscall_handler.hpp | 23 ++++++++++++++++++ .../generic_interrupt_handler.hpp | 8 ------- 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/syscall/main.hpp create mode 100644 arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp new file mode 100644 index 0000000..c75268a --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -0,0 +1,28 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP + +#include "arch/context_switching/syscall/syscall_handler.hpp" + +#include +#include +#include + +namespace teachos::arch::context_switching::syscall +{ + struct arguments + { + uint64_t arg_0{}; + uint64_t arg_1{}; + uint64_t arg_2{}; + uint64_t arg_3{}; + uint64_t arg_4{}; + uint64_t arg_5{}; + }; + + auto enable_syscall() -> void; + + auto syscall(type syscall_number, arguments args = {}) -> uint64_t; + +} // namespace teachos::arch::context_switching::syscall + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP diff --git a/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp new file mode 100644 index 0000000..e076995 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp @@ -0,0 +1,23 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP + +#include + +namespace teachos::arch::context_switching::syscall +{ + enum type : uint64_t + { + WRITE = 1U + }; + + /** + * @brief Handler for SYSCALL instruction. Calls a specific implementation based + * on the register RAX. + * + * @return Returns with SYSRETQ + */ + auto syscall_handler() -> void; + +} // namespace teachos::arch::context_switching::syscall + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_HANDLER_HPP diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index 866d15d..8091a58 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -29,14 +29,6 @@ namespace teachos::arch::interrupt_handling [[gnu::interrupt]] [[gnu::section(".interrupt_text")]] auto generic_interrupt_handler(interrupt_frame * frame) -> void; - /** - * @brief Interrupt handler function for syscalls (INT 0x80). - * - * @param frame Pointer to the interrupt frame containing CPU state. - */ - [[gnu::interrupt]] [[gnu::section(".interrupt_text")]] - auto syscall_interrupt_handler(interrupt_frame * frame) -> void; - } // namespace teachos::arch::interrupt_handling #endif // TEACHOS_ARCH_X86_64_INTERRUPT_HANDLING_GENERIC_INTERRUPT_HANDLER_HPP -- cgit v1.2.3 From ccb0fcb78c0d22ebaeb9aa37f1941b0d44c98038 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 4 May 2025 11:07:48 +0000 Subject: move user-mode code into own namespace and linker section --- .../arch/interrupt_handling/generic_interrupt_handler.hpp | 2 +- arch/x86_64/include/arch/user/main.hpp | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 arch/x86_64/include/arch/user/main.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index 8091a58..2d26668 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -26,7 +26,7 @@ namespace teachos::arch::interrupt_handling * * @param frame Pointer to the interrupt frame containing CPU state. */ - [[gnu::interrupt]] [[gnu::section(".interrupt_text")]] + [[gnu::interrupt]] auto generic_interrupt_handler(interrupt_frame * frame) -> void; } // namespace teachos::arch::interrupt_handling diff --git a/arch/x86_64/include/arch/user/main.hpp b/arch/x86_64/include/arch/user/main.hpp new file mode 100644 index 0000000..7127d07 --- /dev/null +++ b/arch/x86_64/include/arch/user/main.hpp @@ -0,0 +1,10 @@ +#ifndef TEACHOS_ARCH_X86_64_USER_MAIN_HPP +#define TEACHOS_ARCH_X86_64_USER_MAIN_HPP + +namespace teachos::arch::user +{ + auto main() -> void; + +} // namespace teachos::arch::user + +#endif // TEACHOS_ARCH_X86_64_USER_MAIN_HPP \ No newline at end of file -- cgit v1.2.3 From c1dff44858ebdb3cd5a49e84179796e44e7eb91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 5 May 2025 06:41:31 +0000 Subject: Fix recursive include using extra file --- .../include/arch/context_switching/syscall/main.hpp | 20 +++++++++++++------- .../context_switching/syscall/syscall_enable.hpp | 10 ++++++++++ .../context_switching/syscall/syscall_handler.hpp | 7 +------ arch/x86_64/include/arch/user/main.hpp | 2 +- 4 files changed, 25 insertions(+), 14 deletions(-) create mode 100644 arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index c75268a..ae4c2db 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -1,14 +1,22 @@ #ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP #define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_MAIN_HPP -#include "arch/context_switching/syscall/syscall_handler.hpp" - -#include #include -#include namespace teachos::arch::context_switching::syscall { + enum class type : uint64_t + { + WRITE = 1U + }; + + enum class error + { + OK = 0U, + }; + + constexpr bool operator!(error e) { return e == error::OK; } + struct arguments { uint64_t arg_0{}; @@ -19,9 +27,7 @@ namespace teachos::arch::context_switching::syscall uint64_t arg_5{}; }; - auto enable_syscall() -> void; - - auto syscall(type syscall_number, arguments args = {}) -> uint64_t; + auto syscall(type syscall_number, arguments args = {}) -> error; } // namespace teachos::arch::context_switching::syscall diff --git a/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp new file mode 100644 index 0000000..59b97b2 --- /dev/null +++ b/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp @@ -0,0 +1,10 @@ +#ifndef TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP +#define TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP + +namespace teachos::arch::context_switching::syscall +{ + auto enable_syscall() -> void; + +} // namespace teachos::arch::context_switching::syscall + +#endif // TEACHOS_ARCH_X86_64_CONTEXT_SWITCHING_SYSCALL_SYSCALL_ENABLE_HPP diff --git a/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp index e076995..2e7bcd1 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/syscall_handler.hpp @@ -5,16 +5,11 @@ namespace teachos::arch::context_switching::syscall { - enum type : uint64_t - { - WRITE = 1U - }; - /** * @brief Handler for SYSCALL instruction. Calls a specific implementation based * on the register RAX. * - * @return Returns with SYSRETQ + * @return Returns with LEAVE, SYSRETQ */ auto syscall_handler() -> void; diff --git a/arch/x86_64/include/arch/user/main.hpp b/arch/x86_64/include/arch/user/main.hpp index 7127d07..4f1d005 100644 --- a/arch/x86_64/include/arch/user/main.hpp +++ b/arch/x86_64/include/arch/user/main.hpp @@ -7,4 +7,4 @@ namespace teachos::arch::user } // namespace teachos::arch::user -#endif // TEACHOS_ARCH_X86_64_USER_MAIN_HPP \ No newline at end of file +#endif // TEACHOS_ARCH_X86_64_USER_MAIN_HPP -- cgit v1.2.3 From 27d4fb90ebbc754e98ff68ce5bc7839a44ed99c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 5 May 2025 09:22:28 +0000 Subject: Add comments to syscall components --- .../arch/context_switching/syscall/main.hpp | 47 ++++++++++++++++++---- .../context_switching/syscall/syscall_enable.hpp | 8 ++++ 2 files changed, 48 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index ae4c2db..48fa195 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -5,28 +5,61 @@ namespace teachos::arch::context_switching::syscall { + /** + * @brief Possible syscall implementation that should actually be called. + * + * @note Attempts to reflect the Linux interface partially. See https://filippo.io/linux-syscall-table/ for more + * information. + */ enum class type : uint64_t { - WRITE = 1U + WRITE = 1U, ///< Loads the arg_0 parameter as an address pointing to a const char array, which will then be printed + ///< onto the VGA buffer screen. }; + /** + * @brief Possible error codes that can be returned by the different syscall methods called depending on the type + * enum. + */ enum class error { OK = 0U, }; + /** + * @brief Allows to convert the error enum type into a boolean directly. Where any code besides 0 being no error, will + * return true. The remaining errors return true. + * + * @param e Error code that was returned by the syscall. + * @return Return true if there was no error and false otherwise. + */ constexpr bool operator!(error e) { return e == error::OK; } + /** + * @brief Maximum amount of arguments that can be passed to a syscall. Default value is 0 and arguments are only ever + * used depending on the actual enum type and if the method requires thoose parameters. + */ struct arguments { - uint64_t arg_0{}; - uint64_t arg_1{}; - uint64_t arg_2{}; - uint64_t arg_3{}; - uint64_t arg_4{}; - uint64_t arg_5{}; + uint64_t arg_0{}; ///< First optional paramter to the syscall representing the RDI register. + uint64_t arg_1{}; ///< Second optional paramter to the syscall representing the RSI register. + uint64_t arg_2{}; ///< Third optional paramter to the syscall representing the RDX register. + uint64_t arg_3{}; ///< Fourth optional paramter to the syscall representing the R10 register. + uint64_t arg_4{}; ///< Fifth optional paramter to the syscall representing the R8 register. + uint64_t arg_5{}; ///< Sixth optional paramter to the syscall representing the R9 register. }; + /** + * @brief Calls the method associated with the given syscall number and passes the given optional arguments to it, + * over the RDI, RSI, RDX, R10, R8 and R9 register. + * + * @param syscall_number Syscall method that should be called. See enum values in type for possible implemented + * methods. + * @param args Optional arguments passable to the different syscall methods, called depending on the syscall_number. + * Not passing the required parameters to the method, will result in passing 0 instead, which might make the fail or + * not function correctly. + * @return Bool-convertable error code converting to true if the syscall failed or false if it didn't. + */ auto syscall(type syscall_number, arguments args = {}) -> error; } // namespace teachos::arch::context_switching::syscall diff --git a/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp b/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp index 59b97b2..8cb468a 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/syscall_enable.hpp @@ -3,6 +3,14 @@ namespace teachos::arch::context_switching::syscall { + /** + * @brief Enables and sets up internal CPU registers to allow for syscall to function correctly and switch context + * temporarily back to the kernel level. + * + * @note Configures the Model Specific Register required by syscall (LSTAR, FMASK, STAR) with the correct values so + * that the syscall_handler is called and sets the System Call Extension bit on the EFER flags to allow for syscall + * to be used. + */ auto enable_syscall() -> void; } // namespace teachos::arch::context_switching::syscall -- cgit v1.2.3 From 7d2e8bc16e6c1bacb3c676d21ea2245d8132218f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 5 May 2025 11:27:29 +0000 Subject: Remove the addition of USER_ACCESSIBLE flag to every entry created --- .../include/arch/memory/paging/active_page_table.hpp | 2 +- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 16 ++++++++++++---- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 6 ++++++ arch/x86_64/include/arch/memory/paging/page_table.hpp | 3 ++- arch/x86_64/include/arch/user/main.hpp | 5 +++++ 5 files changed, 26 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index 9e91a8c..a4a5b64 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -89,7 +89,7 @@ namespace teachos::arch::memory::paging arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), "[Page Mapper] Unable to map huge pages"); arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); - level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); + level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT | entry::USER_ACCESSIBLE); } /** 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 8d36fde..09e9bf4 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -81,11 +81,12 @@ namespace teachos::arch::memory::paging kernel::cpu::read_control_register(kernel::cpu::control_register::CR3)); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); + active_table[511].set_entry(inactive_table.page_table_level_4_frame, + entry::PRESENT | entry::WRITABLE | entry::USER_ACCESSIBLE); kernel::cpu::tlb_flush_all(); map_elf_kernel_sections(active_table); - page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); + page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE | entry::USER_ACCESSIBLE); kernel::cpu::tlb_flush_all(); temporary_page.unmap_page(active_table); } @@ -136,7 +137,14 @@ namespace teachos::arch::memory::paging allocator::frame_container::iterator const begin{start_frame}; allocator::frame_container::iterator const end{end_frame}; allocator::frame_container const frames{begin, end}; - entry const entry{section.flags}; + entry entry{section.flags}; + + // TODO: Only set this if we are in the .user_text section. + // address: 0000000000216000, offset: 013000, size: varies depending on code not a a good idea + // Alternatively index Nr. 8 could be used to detect section, can also change if we add more section + entry.set_user_accesible(); + + // TODO: Entering User Mode still works, but then attempting to execute an instruction immedatiately fails. for (auto const & frame : frames) { @@ -146,7 +154,7 @@ namespace teachos::arch::memory::paging auto const vga_buffer_frame = allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); - active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); + active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE | entry::USER_ACCESSIBLE); } T & allocator; diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index ef4fe61..5cba1bc 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -71,6 +71,12 @@ namespace teachos::arch::memory::paging */ auto set_unused() -> void; + /** + * @brief Marks the page as accessible in User mode, meaning the underlying std::bitset has the 2nd bit aditonally + * set. + */ + auto set_user_accesible() -> void; + /** * @brief Calculates the physical frame this entry is pointing too, can be null if the page is not present in * memory. diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 60a0a2f..db7ba6c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -94,7 +94,8 @@ namespace teachos::arch::memory::paging { auto const allocated_frame = allocator.allocate_frame(); exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); - this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); + this->operator[](table_index) + .set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE | entry::USER_ACCESSIBLE); // There should now be an entry at the previously not existent index, therefore we can simply access it again. next_handle = next_table(table_index); exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); diff --git a/arch/x86_64/include/arch/user/main.hpp b/arch/x86_64/include/arch/user/main.hpp index 4f1d005..ba30864 100644 --- a/arch/x86_64/include/arch/user/main.hpp +++ b/arch/x86_64/include/arch/user/main.hpp @@ -3,6 +3,11 @@ namespace teachos::arch::user { + /** + * @brief User Main method. If this method finishes there is no code left to run and the whole OS will shut down. + * Additionally this main method is executed at Ring 3 and accessing CPU Registers or Kernel level functionality can + * only be done over syscalls and not directly anymore. + */ auto main() -> void; } // namespace teachos::arch::user -- cgit v1.2.3 From c9f46f3773e7943ce114af888a44f50061c2ac1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 6 May 2025 13:40:42 +0000 Subject: Remove user Mode Access to VGA / Heap and Kernel Methods. --- .../arch/context_switching/syscall/main.hpp | 1 + .../arch/memory/paging/active_page_table.hpp | 7 +++++-- .../include/arch/memory/paging/kernel_mapper.hpp | 22 ++++++++++++---------- .../include/arch/memory/paging/page_table.hpp | 5 +++-- arch/x86_64/include/arch/user/main.hpp | 1 + 5 files changed, 22 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index 48fa195..3af5a5a 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -60,6 +60,7 @@ namespace teachos::arch::context_switching::syscall * not function correctly. * @return Bool-convertable error code converting to true if the syscall failed or false if it didn't. */ + [[gnu::section(".user_text")]] auto syscall(type syscall_number, arguments args = {}) -> error; } // namespace teachos::arch::context_switching::syscall diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index a4a5b64..d77b76c 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -82,14 +82,17 @@ namespace teachos::arch::memory::paging for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { - current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level)); + // Ignore all bits passed besides the entry::USER_ACCESSIBLE bit, because for the entry into the Level 4 up to + // Level 2 page, we always have to set the entry::PRESENT and entry::WRITABLE bit anyway. + current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level), + flags.to_ulong() & entry::USER_ACCESSIBLE); } auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE), "[Page Mapper] Unable to map huge pages"); arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used"); - level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT | entry::USER_ACCESSIBLE); + level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT); } /** 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 09e9bf4..ce74b98 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -81,12 +81,11 @@ namespace teachos::arch::memory::paging kernel::cpu::read_control_register(kernel::cpu::control_register::CR3)); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - active_table[511].set_entry(inactive_table.page_table_level_4_frame, - entry::PRESENT | entry::WRITABLE | entry::USER_ACCESSIBLE); + active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); kernel::cpu::tlb_flush_all(); map_elf_kernel_sections(active_table); - page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE | entry::USER_ACCESSIBLE); + page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); kernel::cpu::tlb_flush_all(); temporary_page.unmap_page(active_table); } @@ -139,12 +138,15 @@ namespace teachos::arch::memory::paging allocator::frame_container const frames{begin, end}; entry entry{section.flags}; - // TODO: Only set this if we are in the .user_text section. - // address: 0000000000216000, offset: 013000, size: varies depending on code not a a good idea - // Alternatively index Nr. 8 could be used to detect section, can also change if we add more section - entry.set_user_accesible(); - - // TODO: Entering User Mode still works, but then attempting to execute an instruction immedatiately fails. + // TODO: Why exactly are this section required or not required? + // Required to be accesible in User Mode: .user_text (Contains the actuall code executed), .boot_bss (Contains + // statically allocated variables), .boot_rodata (Contains constant data stored in ROM) + // Not required: .text, .rodata, .ctors, .dtors, .bss, .data, .boot_data, .boot_text, .init + if (section.physical_address == 0x100000 || section.physical_address == 0x102000 || + section.physical_address == 0x216000) + { + entry.set_user_accesible(); + } for (auto const & frame : frames) { @@ -154,7 +156,7 @@ namespace teachos::arch::memory::paging auto const vga_buffer_frame = allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); - active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE | entry::USER_ACCESSIBLE); + active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); } T & allocator; diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index db7ba6c..7b7e29e 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -81,9 +81,10 @@ namespace teachos::arch::memory::paging * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate * entries when a new page table is required. * @param table_index Index of this page table in the page table one level lower. + * @param flags A bitset of flags that configure the page table entry for this mapping. */ template - auto next_table_or_create(T & allocator, std::size_t table_index) -> page_table_handle + auto next_table_or_create(T & allocator, std::size_t table_index, std::bitset<64U> flags) -> page_table_handle { auto next_handle = next_table(table_index); // If the next table method failed then it means that the page level of the frame we want allocate has not yet @@ -95,7 +96,7 @@ namespace teachos::arch::memory::paging auto const allocated_frame = allocator.allocate_frame(); exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); this->operator[](table_index) - .set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE | entry::USER_ACCESSIBLE); + .set_entry(allocated_frame.value(), flags.to_ulong() | entry::PRESENT | entry::WRITABLE); // There should now be an entry at the previously not existent index, therefore we can simply access it again. next_handle = next_table(table_index); exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); diff --git a/arch/x86_64/include/arch/user/main.hpp b/arch/x86_64/include/arch/user/main.hpp index ba30864..c168a1f 100644 --- a/arch/x86_64/include/arch/user/main.hpp +++ b/arch/x86_64/include/arch/user/main.hpp @@ -8,6 +8,7 @@ namespace teachos::arch::user * Additionally this main method is executed at Ring 3 and accessing CPU Registers or Kernel level functionality can * only be done over syscalls and not directly anymore. */ + [[gnu::section(".user_text")]] auto main() -> void; } // namespace teachos::arch::user -- cgit v1.2.3 From be32189323ba8c46091d6deaf091cf41147426b4 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Wed, 7 May 2025 14:06:25 +0000 Subject: wip custom heap allocation functions for user mode --- .../arch/memory/heap/global_heap_allocator.hpp | 39 ++++++++++++++++++---- .../include/arch/memory/heap/heap_allocator.hpp | 6 ++-- 2 files changed, 37 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index 772f171..bfc7b67 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -45,7 +45,7 @@ namespace teachos::arch::memory::heap * @param size Amount of bytes that should be allocated * @return void* Pointer to the start of the allocatable memory area */ - static auto allocate(std::size_t size) -> void *; + static auto kmalloc(std::size_t size) -> void *; /** * @brief Deallocated all memory associated with the memory area starting from the given pointer address. @@ -53,17 +53,44 @@ namespace teachos::arch::memory::heap * * @param pointer Previously allocated memory area, that should now be freed */ - static auto deallocate(void * pointer) noexcept -> void; + static auto kfree(void * pointer) noexcept -> void; + + /** + * @brief Allocates the given amount of memory and returns the pointer to the start of the allocatable memory area. + * Simply forwards the call to the allocate method of the registered heap_allocation implementation + * + * @param size Amount of bytes that should be allocated + * @return void* Pointer to the start of the allocatable memory area + */ + [[gnu::section(".user_text")]] + static auto malloc(std::size_t size) -> void *; + + /** + * @brief Deallocated all memory associated with the memory area starting from the given pointer address. + * Simply forwards the call to the deallocate method of the registered heap_allocation implementation + * + * @param pointer Previously allocated memory area, that should now be freed + */ + [[gnu::section(".user_text")]] + static auto free(void * pointer) noexcept -> void; private: - static heap_allocator * allocator_instance; ///< Instance used to actually allocate and deallocate + static heap_allocator * kernel_allocator_instance; ///< Instance used to allocate and deallocate kernel heap memory + static heap_allocator * user_allocator_instance; ///< Instance used to allocate and deallocate user heap memory + + /** + * @brief Either returns the previously registered heap allocated or halts further execution + * + * @return Reference to the registered kernel heap allocation + */ + static auto kernel() -> heap_allocator &; /** - * @brief Either returns the previously registered heap allocated or halts furthere execution + * @brief Either returns the previously registered heap allocated or halts further execution * - * @return Reference to the registered heap allocation + * @return Reference to the registered user heap allocation */ - static auto get() -> heap_allocator &; + static auto user() -> heap_allocator &; }; } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp index 6aed3d8..420a1d3 100644 --- a/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp @@ -5,8 +5,10 @@ namespace teachos::arch::memory::heap { - std::size_t constexpr HEAP_START = 0x100000000; - std::size_t constexpr HEAP_SIZE = 100 * 1024; + std::size_t constexpr KERNEL_HEAP_START = 0x100000000; + std::size_t constexpr KERNEL_HEAP_SIZE = 100 * 1024; + std::size_t constexpr USER_HEAP_START = 0x100019000; // Starts directly after kernel heap + std::size_t constexpr USER_HEAP_SIZE = 100 * 1024; /** * @brief Heap allocator interface containing methods required to allocate and deallocate heap memory areas -- cgit v1.2.3 From 0b62fdb3fe657d056a42d7567b67951ba3468738 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 8 May 2025 08:51:52 +0000 Subject: wip allocating heap memory in user mode --- .../arch/memory/heap/global_heap_allocator.hpp | 7 +++- .../arch/memory/heap/user_heap_allocator.hpp | 48 ++++++++++++++++++++++ .../include/arch/memory/paging/kernel_mapper.hpp | 2 +- 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index bfc7b67..d0d1080 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -2,6 +2,7 @@ #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP #include "arch/memory/heap/heap_allocator.hpp" +#include "arch/memory/heap/user_heap_allocator.hpp" namespace teachos::arch::memory::heap { @@ -76,7 +77,8 @@ namespace teachos::arch::memory::heap private: static heap_allocator * kernel_allocator_instance; ///< Instance used to allocate and deallocate kernel heap memory - static heap_allocator * user_allocator_instance; ///< Instance used to allocate and deallocate user heap memory + static user_heap_allocator * + user_allocator_instance; ///< Instance used to allocate and deallocate user heap memory /** * @brief Either returns the previously registered heap allocated or halts further execution @@ -90,7 +92,8 @@ namespace teachos::arch::memory::heap * * @return Reference to the registered user heap allocation */ - static auto user() -> heap_allocator &; + [[gnu::section(".user_text")]] + static auto user() -> user_heap_allocator &; }; } // 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 new file mode 100644 index 0000000..1dab047 --- /dev/null +++ b/arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp @@ -0,0 +1,48 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP + +#include "arch/memory/heap/heap_allocator.hpp" + +#include +#include + +namespace teachos::arch::memory::heap +{ + /** + * @brief Simple heap allocator, which allocates linearly and leaks all allocated memory, because it does not really + * deallocate anything. + */ + struct user_heap_allocator + { + /** + * @brief Constructor. + * + * @param heap_start Start of the allocatable heap area + * @param heap_end End of the allocatable heap area (Start + Size) + */ + user_heap_allocator(std::size_t heap_start, std::size_t heap_end) + : heap_start{heap_start} + , heap_end{heap_end} + , next{heap_start} + { + // Nothing to do + } + + auto allocate(std::size_t size) -> void *; + + /** + * @copybrief heap_allocator::deallocate + * + * @note Simply does nothing, because this allocator leaks all memory + */ + auto deallocate(void * pointer) noexcept -> void; + + private: + std::size_t heap_start; ///< Start of the allocatable heap area + std::size_t heap_end; ///< End of the allocatable heap area + std::atomic_uint64_t next; ///< Current address, which is the start of still unused allocatable heap area + }; + +} // namespace teachos::arch::memory::heap + +#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP 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 ce74b98..6459107 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -143,7 +143,7 @@ namespace teachos::arch::memory::paging // statically allocated variables), .boot_rodata (Contains constant data stored in ROM) // Not required: .text, .rodata, .ctors, .dtors, .bss, .data, .boot_data, .boot_text, .init if (section.physical_address == 0x100000 || section.physical_address == 0x102000 || - section.physical_address == 0x216000) + section.physical_address == 0x217000) { entry.set_user_accesible(); } -- cgit v1.2.3 From d7205b75cda2caff078cea26ff1508f9daa5b4cc Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 8 May 2025 12:34:57 +0000 Subject: make user_allocator_instance be part of user_data section --- arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index d0d1080..6fcab6f 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -77,7 +77,7 @@ namespace teachos::arch::memory::heap private: static heap_allocator * kernel_allocator_instance; ///< Instance used to allocate and deallocate kernel heap memory - static user_heap_allocator * + [[gnu::section(".user_data")]] static user_heap_allocator * user_allocator_instance; ///< Instance used to allocate and deallocate user heap memory /** -- cgit v1.2.3 From d80ecf29baada6242c5181adaec0d1500707cad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 9 May 2025 12:00:23 +0000 Subject: Move necessary code into user text --- arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp | 3 ++- arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp | 2 ++ arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 8 +++++--- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index 6fcab6f..b20a452 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -77,7 +77,8 @@ namespace teachos::arch::memory::heap private: static heap_allocator * kernel_allocator_instance; ///< Instance used to allocate and deallocate kernel heap memory - [[gnu::section(".user_data")]] static user_heap_allocator * + [[gnu::section(".user_data")]] + static user_heap_allocator * user_allocator_instance; ///< Instance used to allocate and deallocate user heap memory /** 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 1dab047..9d00c19 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 @@ -28,6 +28,7 @@ namespace teachos::arch::memory::heap // Nothing to do } + [[gnu::section(".user_text")]] auto allocate(std::size_t size) -> void *; /** @@ -35,6 +36,7 @@ namespace teachos::arch::memory::heap * * @note Simply does nothing, because this allocator leaks all memory */ + [[gnu::section(".user_text")]] auto deallocate(void * pointer) noexcept -> void; private: 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 6459107..95d04f4 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -139,11 +139,13 @@ namespace teachos::arch::memory::paging entry entry{section.flags}; // TODO: Why exactly are this section required or not required? - // Required to be accesible in User Mode: .user_text (Contains the actuall code executed), .boot_bss (Contains - // statically allocated variables), .boot_rodata (Contains constant data stored in ROM) + // Required to be accesible in User Mode: .user_text (Contains the actual code executed), .boot_bss (Contains + // statically allocated variables), .boot_rodata (Contains constant data stored in ROM), .user_data (Contains + // static user variables // Not required: .text, .rodata, .ctors, .dtors, .bss, .data, .boot_data, .boot_text, .init if (section.physical_address == 0x100000 || section.physical_address == 0x102000 || - section.physical_address == 0x217000) + section.physical_address == 0x217000 || section.physical_address == 0x21D000 || + section.physical_address == 0x209000) { entry.set_user_accesible(); } -- cgit v1.2.3 From a5812be4fa8ecc208219682204b14969d7b718b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 9 May 2025 13:15:58 +0000 Subject: Switch uer heap to linked list allocator --- .../arch/memory/heap/user_heap_allocator.hpp | 118 +++++++++++++++++---- 1 file changed, 97 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/include') 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 9d00c19..d698888 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 @@ -1,16 +1,14 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP -#include "arch/memory/heap/heap_allocator.hpp" - -#include -#include +#include "arch/memory/heap/memory_block.hpp" +#include "arch/stl/mutex.hpp" namespace teachos::arch::memory::heap { /** - * @brief Simple heap allocator, which allocates linearly and leaks all allocated memory, because it does not really - * deallocate anything. + * @brief Sorted by address list of memory holes (free memory). Uses free holes itself to save the information, + * containing the size and pointer to the next hole. Resulting in a singly linked list. */ struct user_heap_allocator { @@ -20,31 +18,109 @@ namespace teachos::arch::memory::heap * @param heap_start Start of the allocatable heap area * @param heap_end End of the allocatable heap area (Start + Size) */ - user_heap_allocator(std::size_t heap_start, std::size_t heap_end) - : heap_start{heap_start} - , heap_end{heap_end} - , next{heap_start} - { - // Nothing to do - } + user_heap_allocator(std::size_t heap_start, std::size_t heap_end); + /** + * @copybrief heap_allocator::allocate + * + * @note The specified size is used to find a free memory block with the exact same size, meaning we can remove that + * free memory block from the free list and simply return its address. Or it has to be big enough to hold the size + * and alteast enough memory for another free memory block entry (16 bytes). If the amount of memory of that free + * memory block is in between we cannot use it for our allocation, because we could only return it to the user, but + * the additional bytes, could not be used to create a free memory block. Additionaly the user couldn't know + * they received more memory than wanted. Therefore the memory would simply be unused and because it is neither + * allocated nor deallocated would never be indexed by the free memory list. We would therefore permanently loose + * that memory, to prevent that allocation into free memory blocks like that are impossible. + */ [[gnu::section(".user_text")]] auto allocate(std::size_t size) -> void *; + [[gnu::section(".user_text")]] + auto deallocate(void * pointer) noexcept -> void; + + private: /** - * @copybrief heap_allocator::deallocate + * @brief Returns the smallest allocatable block of heap memory. * - * @note Simply does nothing, because this allocator leaks all memory + * @return Smallest allocatable block of heap memory. + */ + [[gnu::section(".user_text")]] auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); } + + /** + * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it. + * + * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to + * allocate the required size into. + * @param current_block Free memory block we want to remove from the free list and return for the allocation. + * + * @return Previous start address of the memory block we removed, because it can now be used for the allocation. */ [[gnu::section(".user_text")]] - auto deallocate(void * pointer) noexcept -> void; + auto remove_free_memory_block(memory_block * previous_block, memory_block * current_block) -> void *; - private: - std::size_t heap_start; ///< Start of the allocatable heap area - std::size_t heap_end; ///< End of the allocatable heap area - std::atomic_uint64_t next; ///< Current address, which is the start of still unused allocatable heap area - }; + /** + * @brief Splits the given free memory block into two, where the latter block keeps being free and the first + * part will be used for the allocation. + * + * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to + * allocate the required size into. + * @param current_block Free memory block we want to split into a size part for the allocation and the rest for + * future allocations. + * @param size Size we want to allocate at the start of the free memory block. + * + * @return Previous start address of the memory block we just split, because it can now be used for the allocation. + */ + [[gnu::section(".user_text")]] + auto split_free_memory_block(memory_block * previous_block, memory_block * current_block, std::size_t size) + -> void *; + /** + * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it. + * + * @param previous_block Free memory block before the block to allocate in our heap memory. Was to small to + * allocate the required size into. + * @param current_block Free memory block we want to remove from the free list and return for the allocation. + * @param new_block Replaces the current block with the given new block can be nullptr, meaning the free list will + * end here. + * + * @return Previous start address of the memory block we removed, because it can now be used for the allocation. + */ + [[gnu::section(".user_text")]] + auto replace_free_memory_block(memory_block * previous_block, memory_block * current_block, + memory_block * new_block) -> void *; + + /** + * @brief Combines multiple free memory blocks into one if they are adjacent. + * + * @note The internal algorithm for recombination functions like this: + * 1. Check if there is even any memory left, if not the first entry of our linked list should be a nullptr and + * we can therefore set the first entry to our newly created entry. This entry is created in the now deallocated + * memory area. + * 2. If there are more blocks but neither the previous nor the current block are adjacent, we simply create a + * new free memory block of the given size and set the previous next to our block and the next of our block to + * the current block. + * 3. If the current block is adjacent the start address of the newly created block stays the same, but the size + * increases by the amount in the current memory block header. After reading it we also clear the header. + * 4. If the previous block is adjacent the size of the previous block simply increases to include the given + * size as well. + * 5. If the previous block is directly in our start address, so they overlap then it has to mean some or all of + * the region we are trying to deallocate has been freed before. Which would result in a double free therefore + * we halt the execution of the program. + * + * @param previous_block Free memory block before the block to deallocate in our heap memory. + * @param current_block Free memory block after the block to deallocate in our heap memory. + * @param pointer Block to deallocate. + * @param size Size of the block we want to deallocate. + */ + [[gnu::section(".user_text")]] + auto coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer, + std::size_t size) -> void; + + std::size_t heap_start; ///< Start of the allocatable heap area. + std::size_t heap_end; ///< End of the allocatable heap area. + memory_block * first; ///< First free entry in our memory. + stl::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. + }; } // namespace teachos::arch::memory::heap #endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP -- cgit v1.2.3 From f3a976be198d97573b630242c0f833c290c62d81 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 10 May 2025 10:33:26 +0000 Subject: experiment with globally available linker sections and page table entry flags --- .../arch/memory/heap/global_heap_allocator.hpp | 3 +- .../include/arch/memory/paging/kernel_mapper.hpp | 27 +++-- .../include/arch/memory/paging/page_entry.hpp | 2 + arch/x86_64/include/arch/stl/container.hpp | 24 +++- .../arch/stl/contiguous_pointer_iterator.hpp | 34 +++++- .../include/arch/stl/forward_value_iterator.hpp | 15 ++- arch/x86_64/include/arch/stl/mutex.hpp | 3 + arch/x86_64/include/arch/stl/shared_pointer.hpp | 40 ++++++- arch/x86_64/include/arch/stl/stack.hpp | 42 ++++++- arch/x86_64/include/arch/stl/unique_pointer.hpp | 37 +++++- arch/x86_64/include/arch/stl/vector.hpp | 126 +++++++++++++++++---- 11 files changed, 298 insertions(+), 55 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index b20a452..6fcab6f 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -77,8 +77,7 @@ namespace teachos::arch::memory::heap private: static heap_allocator * kernel_allocator_instance; ///< Instance used to allocate and deallocate kernel heap memory - [[gnu::section(".user_data")]] - static user_heap_allocator * + [[gnu::section(".user_data")]] static user_heap_allocator * user_allocator_instance; ///< Instance used to allocate and deallocate user heap memory /** 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 95d04f4..05fde8b 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -40,6 +40,10 @@ namespace teachos::arch::memory::paging */ auto remap_kernel() -> active_page_table & { + // Set Page Global Enable bit + auto cr4 = kernel::cpu::read_control_register(kernel::cpu::control_register::CR4); + kernel::cpu::write_control_register(kernel::cpu::control_register::CR4, cr4 | 0x80); + temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; auto & active_table = active_page_table::create_or_get(); auto const frame = allocator.allocate_frame(); @@ -138,14 +142,21 @@ namespace teachos::arch::memory::paging allocator::frame_container const frames{begin, end}; entry entry{section.flags}; - // TODO: Why exactly are this section required or not required? - // Required to be accesible in User Mode: .user_text (Contains the actual code executed), .boot_bss (Contains - // statically allocated variables), .boot_rodata (Contains constant data stored in ROM), .user_data (Contains - // static user variables - // Not required: .text, .rodata, .ctors, .dtors, .bss, .data, .boot_data, .boot_text, .init - if (section.physical_address == 0x100000 || section.physical_address == 0x102000 || - section.physical_address == 0x217000 || section.physical_address == 0x21D000 || - section.physical_address == 0x209000) + // Required to be accesible in User Mode: + // - .user_text (Contains the actual code executed) + // - .boot_bss (Contains statically allocated variables) + // - .boot_rodata (Contains constant data stored in ROM) + // - .user_data (Contains static user variables) + if (section.physical_address == 0x100000 /* .boot_rodata */ || + section.physical_address == 0x102000 /* .boot_bss */ || + section.physical_address == 0x218000 /* .stl_text */) + { + entry.set_user_accesible(); + entry.set_global(); + } + + if (section.physical_address == 0x217000 /* .user_text */ || + section.physical_address == 0x21D000 /* .user_data */) { entry.set_user_accesible(); } diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 5cba1bc..6ee1a13 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -77,6 +77,8 @@ namespace teachos::arch::memory::paging */ auto set_user_accesible() -> void; + auto set_global() -> void; + /** * @brief Calculates the physical frame this entry is pointing too, can be null if the page is not present in * memory. diff --git a/arch/x86_64/include/arch/stl/container.hpp b/arch/x86_64/include/arch/stl/container.hpp index b0f513b..4ea08c7 100644 --- a/arch/x86_64/include/arch/stl/container.hpp +++ b/arch/x86_64/include/arch/stl/container.hpp @@ -48,7 +48,11 @@ namespace teachos::arch::stl * * @return Iterator pointing to first element of the memory area. */ - auto begin() const -> iterator { return begin_itr; } + [[gnu::section(".stl_text")]] + auto begin() const -> iterator + { + return begin_itr; + } /** * @brief Returns the iterator pointing to one past the last element of the memory area. @@ -56,7 +60,11 @@ namespace teachos::arch::stl * * @return Iterator pointing to one past the last element of the memory area. */ - auto end() const -> iterator { return end_itr; } + [[gnu::section(".stl_text")]] + auto end() const -> iterator + { + return end_itr; + } /** * @brief Calculates the size of this container, simply subtracts the iterator pointing to the first element by the @@ -64,14 +72,22 @@ namespace teachos::arch::stl * * @return Actual size of this container. */ - auto size() const -> size_type { return std::distance(begin(), end()); } + [[gnu::section(".stl_text")]] + auto size() const -> size_type + { + return std::distance(begin(), end()); + } /** * @brief Calcualtes the size and returns true if the size is 0 and the container therefore emtpy. * * @return Whether the container is empty, size being 0 or not */ - auto empty() const -> bool { return size() == 0; } + [[gnu::section(".stl_text")]] + auto empty() const -> bool + { + return size() == 0; + } private: iterator begin_itr = {}; ///< Pointer to the first element of the given template type. diff --git a/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp b/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp index d15d2e2..f2dfb2b 100644 --- a/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp +++ b/arch/x86_64/include/arch/stl/contiguous_pointer_iterator.hpp @@ -45,20 +45,29 @@ namespace teachos::arch::stl * * @return Reference to the value. */ - auto operator*() const -> reference_type { return *ptr; } + [[gnu::section(".stl_text")]] + auto operator*() const -> reference_type + { + return *ptr; + } /** * @brief Get underlying value, which is the intially passed pointer. * * @return Pointer to the underlying value passed intially. */ - auto operator->() const -> pointer_type { return ptr; } + [[gnu::section(".stl_text")]] + auto operator->() const -> pointer_type + { + return ptr; + } /** * @brief Pre decrement operator. Returns a reference to the changed address. * * @return Reference to the decremented underlying address. */ + [[gnu::section(".stl_text")]] auto operator--() -> contiguous_pointer_iterator & { contiguous_pointer_iterator const old_value = *this; @@ -71,6 +80,7 @@ namespace teachos::arch::stl * * @return Reference to the incremented underlying address. */ + [[gnu::section(".stl_text")]] auto operator++() -> contiguous_pointer_iterator & { ++ptr; @@ -82,6 +92,7 @@ namespace teachos::arch::stl * * @return Copy of the decremented underlying address. */ + [[gnu::section(".stl_text")]] auto operator--(int) -> contiguous_pointer_iterator { auto const old_value = *this; @@ -94,6 +105,7 @@ namespace teachos::arch::stl * * @return Copy of the incremented underlying address. */ + [[gnu::section(".stl_text")]] auto operator++(int) -> contiguous_pointer_iterator { auto const old_value = *this; @@ -107,6 +119,7 @@ namespace teachos::arch::stl * @param value Value we want to add to the underlying address. * @return Reference to the changed underlying address. */ + [[gnu::section(".stl_text")]] auto operator+=(difference_type value) -> contiguous_pointer_iterator & { ptr += value; @@ -119,6 +132,7 @@ namespace teachos::arch::stl * @param value Value we want to subtract from the underlying address. * @return Reference to the changed underlying address. */ + [[gnu::section(".stl_text")]] auto operator-=(difference_type value) -> contiguous_pointer_iterator & { ptr -= value; @@ -131,6 +145,7 @@ namespace teachos::arch::stl * @param value Value we want to add to a copy of the underlying address. * @return Copy of underlying address incremented by the given value. */ + [[gnu::section(".stl_text")]] auto operator+(difference_type value) const -> contiguous_pointer_iterator { return contiguous_pointer_iterator{ptr + value}; @@ -142,6 +157,7 @@ namespace teachos::arch::stl * @param value Value we want to subtrcat from a copy of the underlying address. * @return Copy of underlying address decremented by the given value. */ + [[gnu::section(".stl_text")]] auto operator-(difference_type value) const -> contiguous_pointer_iterator { return contiguous_pointer_iterator{ptr - value}; @@ -153,7 +169,11 @@ namespace teachos::arch::stl * @param other Other iterator we want to substract the underlying address with ours. * @return Size difference between the underlying address of this instance and the given iterator. */ - auto operator-(const contiguous_pointer_iterator & other) const -> difference_type { return ptr - other.ptr; } + [[gnu::section(".stl_text")]] + auto operator-(const contiguous_pointer_iterator & other) const -> difference_type + { + return ptr - other.ptr; + } /** * @brief Index operator overload. Returns a reference to the value at the given index. Simply returns the @@ -162,7 +182,11 @@ namespace teachos::arch::stl * @param index Index we want to access and get the value from. * @return Reference to the value at the given index. */ - auto operator[](difference_type index) const -> value_type & { return *(ptr + index); } + [[gnu::section(".stl_text")]] + auto operator[](difference_type index) const -> value_type & + { + return *(ptr + index); + } /** * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. @@ -170,6 +194,7 @@ namespace teachos::arch::stl * @param other Other iterator to compare to. * @return Whether both iterators point to the same underlying address in memory. */ + [[gnu::section(".stl_text")]] auto operator==(contiguous_pointer_iterator const & other) const -> bool = default; /** @@ -178,6 +203,7 @@ namespace teachos::arch::stl * @param other Other iterator to compare to. * @return Whether the given iterator is smaller or larger than this iterator. */ + [[gnu::section(".stl_text")]] auto operator<=>(contiguous_pointer_iterator const & other) const -> std::strong_ordering = default; private: diff --git a/arch/x86_64/include/arch/stl/forward_value_iterator.hpp b/arch/x86_64/include/arch/stl/forward_value_iterator.hpp index 7c30964..be3d8e6 100644 --- a/arch/x86_64/include/arch/stl/forward_value_iterator.hpp +++ b/arch/x86_64/include/arch/stl/forward_value_iterator.hpp @@ -60,20 +60,29 @@ namespace teachos::arch::stl * * @return Reference to the value. */ - auto operator*() const -> const_reference_type { return value; } + [[gnu::section(".stl_text")]] + auto operator*() const -> const_reference_type + { + return value; + } /** * @brief Gets pointer to the underlying value passed intially. * * @return Pointer to the underlying value passed intially. */ - auto operator->() const -> const_pointer_type { return &value; } + [[gnu::section(".stl_text")]] + auto operator->() const -> const_pointer_type + { + return &value; + } /** * @brief Pre increment operator. Returns a reference to the changed value. * * @return Reference to the incremented underlying value. */ + [[gnu::section(".stl_text")]] auto operator++() -> forward_value_iterator & { ++value; @@ -85,6 +94,7 @@ namespace teachos::arch::stl * * @return Copy of the incremented underlying value. */ + [[gnu::section(".stl_text")]] auto operator++(int) -> forward_value_iterator { auto const old_value = *this; @@ -98,6 +108,7 @@ namespace teachos::arch::stl * @param other Other iterator to compare to. * @return Whether both iterators point to the same underlying address in memory. */ + [[gnu::section(".stl_text")]] auto operator==(forward_value_iterator const & other) const -> bool = default; private: diff --git a/arch/x86_64/include/arch/stl/mutex.hpp b/arch/x86_64/include/arch/stl/mutex.hpp index d8fd9dc..a7d297d 100644 --- a/arch/x86_64/include/arch/stl/mutex.hpp +++ b/arch/x86_64/include/arch/stl/mutex.hpp @@ -34,6 +34,7 @@ namespace teachos::arch::stl /** * @brief Lock the mutex (blocks for as long as it is not available). */ + [[gnu::section(".stl_text")]] auto lock() -> void; /** @@ -41,11 +42,13 @@ namespace teachos::arch::stl * * @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: diff --git a/arch/x86_64/include/arch/stl/shared_pointer.hpp b/arch/x86_64/include/arch/stl/shared_pointer.hpp index 1ddc182..c9796a8 100644 --- a/arch/x86_64/include/arch/stl/shared_pointer.hpp +++ b/arch/x86_64/include/arch/stl/shared_pointer.hpp @@ -25,6 +25,7 @@ namespace teachos::arch::stl * * @param pointer A pointer to an object to manage (default is nullptr). */ + [[gnu::section(".stl_text")]] explicit shared_pointer(T * pointer = nullptr) : pointer(pointer) , ref_count(new std::atomic(pointer != nullptr ? 1 : 0)) @@ -37,6 +38,7 @@ namespace teachos::arch::stl * * @param other The shared_pointer to copy from. */ + [[gnu::section(".stl_text")]] shared_pointer(const shared_pointer & other) : pointer(other.pointer) , ref_count(other.ref_count) @@ -52,6 +54,7 @@ namespace teachos::arch::stl * * @param other The shared_pointer to move from. */ + [[gnu::section(".stl_text")]] shared_pointer(shared_pointer && other) noexcept : pointer(other.pointer) , ref_count(other.ref_count) @@ -68,6 +71,7 @@ namespace teachos::arch::stl * @param other Another smart pointer to share the ownership with. * @return Reference to this shared pointer. */ + [[gnu::section(".stl_text")]] shared_pointer & operator=(const shared_pointer & other) { if (this != &other) @@ -92,6 +96,7 @@ namespace teachos::arch::stl * @param other Another smart pointer to acquire the ownership from. * @return Reference to this shared pointer. */ + [[gnu::section(".stl_text")]] shared_pointer & operator=(shared_pointer && other) noexcept { if (this != &other) @@ -109,13 +114,18 @@ namespace teachos::arch::stl /** * @brief Destructor. Cleans up resources if necessary. */ - ~shared_pointer() { cleanup(); } + [[gnu::section(".stl_text")]] + ~shared_pointer() + { + cleanup(); + } /** * @brief Replaces the managed object. * * @param ptr Pointer to a new object to manage (default = nullptr). */ + [[gnu::section(".stl_text")]] void reset(T * ptr = nullptr) { cleanup(); @@ -129,6 +139,7 @@ namespace teachos::arch::stl * * @param other The shared_pointer to swap with. */ + [[gnu::section(".stl_text")]] void swap(shared_pointer & other) { std::swap(pointer, other.pointer); @@ -140,21 +151,33 @@ namespace teachos::arch::stl * * @return Returns the object owned by *this, equivalent to *get(). */ - auto operator*() const -> T & { return *pointer; } + [[gnu::section(".stl_text")]] + auto operator*() const -> T & + { + return *pointer; + } /** * @brief Member access operator. * * @return Returns a pointer to the object owned by *this, i.e. get(). */ - auto operator->() const -> T * { return pointer; } + [[gnu::section(".stl_text")]] + auto operator->() const -> T * + { + return pointer; + } /** * @brief Returns a pointer to the managed object or nullptr if no object is owned. * * @return Pointer to the managed object or nullptr if no object is owned. */ - auto get() const -> T * { return pointer; } + [[gnu::section(".stl_text")]] + auto get() const -> T * + { + return pointer; + } /** * @brief Returns the number of different shared_pointer instances (*this included) managing the current object. If @@ -167,6 +190,7 @@ namespace teachos::arch::stl * @return The number of Shared_pointer instances managing the current object or ​0​ if there is no managed * object. */ + [[gnu::section(".stl_text")]] auto use_count() const -> std::size_t { if (pointer != nullptr) @@ -182,17 +206,23 @@ namespace teachos::arch::stl * * @return true if *this owns an object, false otherwise. */ - explicit operator bool() const { return pointer != nullptr; } + [[gnu::section(".stl_text")]] + explicit operator bool() const + { + return pointer != nullptr; + } /** * @brief Defaulted three-way comparator operator. */ + [[gnu::section(".stl_text")]] auto operator<=>(const shared_pointer & other) const = default; private: /** * @brief Releases ownership and deletes the object if this was the last ereference to the owned managed object. */ + [[gnu::section(".stl_text")]] auto cleanup() -> void { if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0) diff --git a/arch/x86_64/include/arch/stl/stack.hpp b/arch/x86_64/include/arch/stl/stack.hpp index 9ecf0ca..48bcf10 100644 --- a/arch/x86_64/include/arch/stl/stack.hpp +++ b/arch/x86_64/include/arch/stl/stack.hpp @@ -35,6 +35,7 @@ namespace teachos::arch::stl * @param n Amount of elements we want to create and set the given value for. * @param initial Inital value of all elements in the underlying data array. */ + [[gnu::section(".stl_text")]] explicit stack(size_type n, value_type initial = value_type{}) : _container(n, initial) { @@ -49,6 +50,7 @@ namespace teachos::arch::stl * @param last Input iterator to one past the last element in the range we want to copy from. */ template + [[gnu::section(".stl_text")]] explicit stack(InputIterator first, InputIterator last) : _container(first, last) { @@ -60,6 +62,7 @@ namespace teachos::arch::stl * * @param initalizer_list List we want to copy all elements from. */ + [[gnu::section(".stl_text")]] explicit stack(std::initializer_list initalizer_list) : _container(initalizer_list) { @@ -74,6 +77,7 @@ namespace teachos::arch::stl * * @param other Other instance of stack we want to copy the data from. */ + [[gnu::section(".stl_text")]] stack(stack const & other) : _container(other) { @@ -89,7 +93,11 @@ namespace teachos::arch::stl * @param other Other instance of vector we want to copy the data from. * @return Newly created copy. */ - stack & operator=(stack const & other) { _container = other; } + [[gnu::section(".stl_text")]] + stack & operator=(stack const & other) + { + _container = other; + } /** * @brief Destructor. @@ -102,7 +110,11 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - auto size() const -> size_type { return _container.size(); } + [[gnu::section(".stl_text")]] + auto size() const -> size_type + { + return _container.size(); + } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -110,7 +122,11 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - auto top() -> reference { return _container.back(); } + [[gnu::section(".stl_text")]] + auto top() -> reference + { + return _container.back(); + } /** * @brief Returns a reference to the last element in the container. Calling back on an empty container causes @@ -118,7 +134,11 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ - auto top() const -> const_reference { return _container.back(); } + [[gnu::section(".stl_text")]] + auto top() const -> const_reference + { + return _container.back(); + } /** * @brief Appends the given element value to the end of the container. The element is assigned through the @@ -133,6 +153,7 @@ namespace teachos::arch::stl * @param value The value of the element to append. */ template + [[gnu::section(".stl_text")]] auto push(U && value) -> void { _container.push_back(std::forward(value)); @@ -152,6 +173,7 @@ namespace teachos::arch::stl * @return value_type& */ template + [[gnu::section(".stl_text")]] auto emplace(Args &&... args) -> reference { _container.emplace_back(std::forward(args)...); @@ -164,14 +186,22 @@ namespace teachos::arch::stl * further execution. Iterators and references to the last element are invalidated. The end() * iterator is also invalidated. */ - auto pop() -> void { _container.pop_back(); } + [[gnu::section(".stl_text")]] + auto pop() -> void + { + _container.pop_back(); + } /** * @brief Wheter there are currently any items this container or not. * * @return True if there are no elements, false if there are. */ - auto empty() const -> bool { return _container.empty(); } + [[gnu::section(".stl_text")]] + auto empty() const -> bool + { + return _container.empty(); + } private: container_type _container = {}; ///< Underlying container used by the stack to actually save the data. diff --git a/arch/x86_64/include/arch/stl/unique_pointer.hpp b/arch/x86_64/include/arch/stl/unique_pointer.hpp index 899a35b..03b4ef3 100644 --- a/arch/x86_64/include/arch/stl/unique_pointer.hpp +++ b/arch/x86_64/include/arch/stl/unique_pointer.hpp @@ -17,6 +17,7 @@ namespace teachos::arch::stl * * @param ptr A pointer to an object to manage (default is nullptr). */ + [[gnu::section(".stl_text")]] explicit unique_pointer(T * ptr = nullptr) : pointer(ptr) { @@ -26,7 +27,11 @@ namespace teachos::arch::stl /** * @brief Destructor that deletes the managed object. */ - ~unique_pointer() { delete pointer; } + [[gnu::section(".stl_text")]] + ~unique_pointer() + { + delete pointer; + } /** * @brief Deleted copy constructor to enforce unique ownership. @@ -43,6 +48,7 @@ namespace teachos::arch::stl * * @param other Unique pointer to move from. */ + [[gnu::section(".stl_text")]] unique_pointer(unique_pointer && other) noexcept : pointer(other.pointer) { @@ -55,6 +61,7 @@ namespace teachos::arch::stl * @param other Smart pointer from which ownership will be transferred. * @return Reference to this unique pointer. */ + [[gnu::section(".stl_text")]] auto operator=(unique_pointer && other) noexcept -> unique_pointer & { if (this != &other) @@ -71,28 +78,44 @@ namespace teachos::arch::stl * * @return Returns the object owned by *this, equivalent to *get(). */ - auto operator*() const -> T & { return *pointer; } + [[gnu::section(".stl_text")]] + auto operator*() const -> T & + { + return *pointer; + } /** * @brief Member access operator. * * @return Returns a pointer to the object owned by *this, i.e. get(). */ - auto operator->() const -> T * { return pointer; } + [[gnu::section(".stl_text")]] + auto operator->() const -> T * + { + return pointer; + } /** * @brief Returns a pointer to the managed object or nullptr if no object is owned. * * @return Pointer to the managed object or nullptr if no object is owned. */ - auto get() const -> T * { return pointer; } + [[gnu::section(".stl_text")]] + auto get() const -> T * + { + return pointer; + } /** * @brief Checks whether *this owns an object, i.e. whether get() != nullptr. * * @return true if *this owns an object, false otherwise. */ - explicit operator bool() const noexcept { return pointer != nullptr; } + [[gnu::section(".stl_text")]] + explicit operator bool() const noexcept + { + return pointer != nullptr; + } /** * @brief Releases the ownership of the managed object, if any. @@ -102,6 +125,7 @@ namespace teachos::arch::stl * @return Pointer to the managed object or nullptr if there was no managed object, i.e. the value which would be * returned by get() before the call. */ + [[gnu::section(".stl_text")]] auto release() -> T * { T * temp = pointer; @@ -118,6 +142,7 @@ namespace teachos::arch::stl * * @param ptr Pointer to a new object to manage (default = nullptr). */ + [[gnu::section(".stl_text")]] auto reset(T * ptr = nullptr) -> void { delete pointer; @@ -129,6 +154,7 @@ namespace teachos::arch::stl * * @param other Another unique_ptr object to swap the managed object and the deleter with. */ + [[gnu::section(".stl_text")]] auto swap(unique_pointer & other) -> void { using std::swap; @@ -138,6 +164,7 @@ namespace teachos::arch::stl /** * @brief Defaulted three-way comparator operator. */ + [[gnu::section(".stl_text")]] auto operator<=>(const unique_pointer & other) const = default; private: diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp index c7d7853..5314029 100644 --- a/arch/x86_64/include/arch/stl/vector.hpp +++ b/arch/x86_64/include/arch/stl/vector.hpp @@ -101,6 +101,7 @@ namespace teachos::arch::stl * @param other Other instance of vector we want to copy the data from. * @return Newly created copy. */ + [[gnu::section(".stl_text")]] vector & operator=(vector const & other) { delete[] _data; @@ -122,7 +123,11 @@ namespace teachos::arch::stl * * @return Current amount of elements. */ - auto size() const -> size_type { return _size; } + [[gnu::section(".stl_text")]] + auto size() const -> size_type + { + return _size; + } /** * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we @@ -130,7 +135,11 @@ namespace teachos::arch::stl * * @return Current amount of space the vector has for elements. */ - auto capacity() const -> size_type { return _capacity; } + [[gnu::section(".stl_text")]] + auto capacity() const -> size_type + { + return _capacity; + } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -140,7 +149,11 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - auto operator[](size_type index) -> reference { return _data[index]; } + [[gnu::section(".stl_text")]] + auto operator[](size_type index) -> reference + { + return _data[index]; + } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -150,7 +163,11 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ - auto operator[](size_type index) const -> const_reference { return _data[index]; } + [[gnu::section(".stl_text")]] + auto operator[](size_type index) const -> const_reference + { + return _data[index]; + } /** * @brief Array indexing operator. Allowing to access element at the given index. @@ -160,6 +177,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ + [[gnu::section(".stl_text")]] auto at(size_type index) -> reference { throw_if_out_of_range(index); @@ -174,6 +192,7 @@ namespace teachos::arch::stl * @param index Index we want to access elements at. * @return Reference to the underlying element. */ + [[gnu::section(".stl_text")]] auto at(size_type index) const -> const_reference { throw_if_out_of_range(index); @@ -193,6 +212,7 @@ namespace teachos::arch::stl * @param value The value of the element to append. */ template + [[gnu::section(".stl_text")]] auto push_back(U && value) -> void { increase_capacity_if_full(); @@ -214,6 +234,7 @@ namespace teachos::arch::stl * @return value_type& */ template + [[gnu::section(".stl_text")]] auto emplace_back(Args &&... args) -> value_type & { increase_capacity_if_full(); @@ -227,6 +248,7 @@ namespace teachos::arch::stl * further execution. Iterators and references to the last element are invalidated. The end() * iterator is also invalidated. */ + [[gnu::section(".stl_text")]] auto pop_back() -> void { throw_if_empty(); @@ -239,7 +261,11 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - auto begin() noexcept -> pointer { return _data; } + [[gnu::section(".stl_text")]] + auto begin() noexcept -> pointer + { + return _data; + } /** * @brief Returns an iterator to the first element of the vector. @@ -247,7 +273,11 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - auto begin() const noexcept -> const_pointer { return _data; } + [[gnu::section(".stl_text")]] + auto begin() const noexcept -> const_pointer + { + return _data; + } /** * @brief Returns an iterator to the first element of the vector. @@ -255,7 +285,11 @@ namespace teachos::arch::stl * * @return Iterator to the first element. */ - auto cbegin() const noexcept -> const_pointer { return begin(); } + [[gnu::section(".stl_text")]] + auto cbegin() const noexcept -> const_pointer + { + return begin(); + } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -263,7 +297,11 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - auto rbegin() noexcept -> pointer { return _data + _size - 1; } + [[gnu::section(".stl_text")]] + auto rbegin() noexcept -> pointer + { + return _data + _size - 1; + } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -271,7 +309,11 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - auto rbegin() const noexcept -> const_pointer { return _data + _size - 1; } + [[gnu::section(".stl_text")]] + auto rbegin() const noexcept -> const_pointer + { + return _data + _size - 1; + } /** * @brief Returns a reverse iterator to the first element of the reversed vector. It corresponds to the last element @@ -279,7 +321,11 @@ namespace teachos::arch::stl * * @return Reverse iterator to the first element. */ - auto crbegin() const noexcept -> const_pointer { return rbegin(); } + [[gnu::section(".stl_text")]] + auto crbegin() const noexcept -> const_pointer + { + return rbegin(); + } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -287,7 +333,11 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - auto end() noexcept -> pointer { return _data + _size; } + [[gnu::section(".stl_text")]] + auto end() noexcept -> pointer + { + return _data + _size; + } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -295,7 +345,11 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - auto end() const noexcept -> const_pointer { return _data + _size; } + [[gnu::section(".stl_text")]] + auto end() const noexcept -> const_pointer + { + return _data + _size; + } /** * @brief Returns an iterator to the element following the last element of the vector. This element acts as a @@ -303,7 +357,11 @@ namespace teachos::arch::stl * * @return Iterator to the element following the last element. */ - auto cend() const noexcept -> const_pointer { return end(); } + [[gnu::section(".stl_text")]] + auto cend() const noexcept -> const_pointer + { + return end(); + } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -312,7 +370,11 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - auto rend() noexcept -> pointer { return _data + size - 1; } + [[gnu::section(".stl_text")]] + auto rend() noexcept -> pointer + { + return _data + size - 1; + } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -321,7 +383,11 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - auto rend() const noexcept -> const_pointer { return _data + size - 1; } + [[gnu::section(".stl_text")]] + auto rend() const noexcept -> const_pointer + { + return _data + size - 1; + } /** * @brief Returns a reverse iterator to the element following the last element of the reversed vector. It @@ -330,7 +396,11 @@ namespace teachos::arch::stl * * @return Reverse iterator to the element following the last element. */ - auto crend() const noexcept -> const_pointer { return rbegin(); } + [[gnu::section(".stl_text")]] + auto crend() const noexcept -> const_pointer + { + return rbegin(); + } /** * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range @@ -340,7 +410,11 @@ namespace teachos::arch::stl * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal * to the address of the first element. */ - auto data() -> pointer { return _data; } + [[gnu::section(".stl_text")]] + auto data() -> pointer + { + return _data; + } /** * @brief Returns a pointer to the underlying array serving as element storage. The pointer is such that range @@ -350,7 +424,11 @@ namespace teachos::arch::stl * @return Pointer to the underlying element storage. For non-empty containers, the returned pointer compares equal * to the address of the first element. */ - auto data() const -> const_pointer { return _data; } + [[gnu::section(".stl_text")]] + auto data() const -> const_pointer + { + return _data; + } /** * @brief Returns a reference to the first element in the container. Calling front on an empty container causes @@ -358,6 +436,7 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ + [[gnu::section(".stl_text")]] auto front() -> reference { throw_if_empty(); @@ -370,6 +449,7 @@ namespace teachos::arch::stl * * @return Reference to the first element. */ + [[gnu::section(".stl_text")]] auto front() const -> const_reference { throw_if_empty(); @@ -382,6 +462,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ + [[gnu::section(".stl_text")]] auto back() -> reference { throw_if_empty(); @@ -394,6 +475,7 @@ namespace teachos::arch::stl * * @return Reference to the last element. */ + [[gnu::section(".stl_text")]] auto back() const -> const_reference { throw_if_empty(); @@ -427,6 +509,7 @@ namespace teachos::arch::stl * * @param new_capacity New capacity of the vector, in number of elements */ + [[gnu::section(".stl_text")]] auto reserve(size_type new_capacity) -> void { if (new_capacity <= _capacity) @@ -448,6 +531,7 @@ namespace teachos::arch::stl * If reallocation occurs, all iterators (including the end() iterator) and all references to the elements are * invalidated. If no reallocation occurs, no iterators or references are invalidated. */ + [[gnu::section(".stl_text")]] auto shrink_to_fit() -> void { if (_size == _capacity) @@ -468,7 +552,11 @@ namespace teachos::arch::stl * * @return True if there are no elements, false if there are. */ - auto empty() const -> bool { return _size <= 0; } + [[gnu::section(".stl_text")]] + auto empty() const -> bool + { + return _size <= 0; + } private: /** -- cgit v1.2.3 From c4261dd2312f8c55dc795f2674a03d6341f821ea Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 10 May 2025 11:45:38 +0000 Subject: continue experimenting with user heap --- .../x86_64/include/arch/memory/heap/user_heap_allocator.hpp | 1 + arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') 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 d698888..c50d2f6 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 @@ -18,6 +18,7 @@ namespace teachos::arch::memory::heap * @param heap_start Start of the allocatable heap area * @param heap_end End of the allocatable heap area (Start + Size) */ + [[gnu::section(".user_text")]] user_heap_allocator(std::size_t heap_start, std::size_t heap_end); /** 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 05fde8b..bc36361 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -143,10 +143,11 @@ namespace teachos::arch::memory::paging entry entry{section.flags}; // Required to be accesible in User Mode: - // - .user_text (Contains the actual code executed) - // - .boot_bss (Contains statically allocated variables) // - .boot_rodata (Contains constant data stored in ROM) + // - .boot_bss (Contains statically allocated variables) + // - .user_text (Contains the actual code executed) // - .user_data (Contains static user variables) + // - .stl_text (Contains code for custom std implementations) if (section.physical_address == 0x100000 /* .boot_rodata */ || section.physical_address == 0x102000 /* .boot_bss */ || section.physical_address == 0x218000 /* .stl_text */) @@ -155,8 +156,14 @@ namespace teachos::arch::memory::paging entry.set_global(); } + // TODO: We should be able to remove this somehow + if (section.physical_address == 0x209000 /* .text */) + { + entry.set_user_accesible(); + } + if (section.physical_address == 0x217000 /* .user_text */ || - section.physical_address == 0x21D000 /* .user_data */) + section.physical_address == 0x21E000 /* .user_data */) { entry.set_user_accesible(); } -- cgit v1.2.3 From 955ab48fe6329b2cbc8c5855a8ba7290185d0ea3 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 11 May 2025 07:20:54 +0000 Subject: rename page table entry function --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 8 ++++---- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/include') 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 bc36361..7321548 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -142,7 +142,7 @@ namespace teachos::arch::memory::paging allocator::frame_container const frames{begin, end}; entry entry{section.flags}; - // Required to be accesible in User Mode: + // Required to be accessible in User Mode: // - .boot_rodata (Contains constant data stored in ROM) // - .boot_bss (Contains statically allocated variables) // - .user_text (Contains the actual code executed) @@ -152,20 +152,20 @@ namespace teachos::arch::memory::paging section.physical_address == 0x102000 /* .boot_bss */ || section.physical_address == 0x218000 /* .stl_text */) { - entry.set_user_accesible(); + entry.set_user_accessible(); entry.set_global(); } // TODO: We should be able to remove this somehow if (section.physical_address == 0x209000 /* .text */) { - entry.set_user_accesible(); + entry.set_user_accessible(); } if (section.physical_address == 0x217000 /* .user_text */ || section.physical_address == 0x21E000 /* .user_data */) { - entry.set_user_accesible(); + entry.set_user_accessible(); } for (auto const & frame : frames) diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 6ee1a13..03cdb1a 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -75,7 +75,7 @@ namespace teachos::arch::memory::paging * @brief Marks the page as accessible in User mode, meaning the underlying std::bitset has the 2nd bit aditonally * set. */ - auto set_user_accesible() -> void; + auto set_user_accessible() -> void; auto set_global() -> void; -- cgit v1.2.3 From 833cd6446d9981a262959749c0e248e33b54c174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 11 May 2025 08:48:57 +0000 Subject: Adjust user heap allocator with expanding heap functionality --- .../arch/context_switching/syscall/main.hpp | 23 +++++++++++++++++++--- .../arch/memory/heap/user_heap_allocator.hpp | 9 +++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index 3af5a5a..8587ab2 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -15,6 +15,10 @@ namespace teachos::arch::context_switching::syscall { WRITE = 1U, ///< Loads the arg_0 parameter as an address pointing to a const char array, which will then be printed ///< onto the VGA buffer screen. + EXPAND_HEAP = 2U, /// Expands the User Heap by additonally mapping 100 KiB of virtual page memory. Ignores the + /// parameters and uses them as out parameters instead, where arg_0 is the start of the newly + /// mapped heap area and arg_1 is the size of the entire area. Can be less than 100 KiB if less + /// space remains. }; /** @@ -23,7 +27,8 @@ namespace teachos::arch::context_switching::syscall */ enum class error { - OK = 0U, + OK = 0U, ///< No error occured in syscall. + OUT_OF_MEMORY = 1U, ///< Expanding heap failed because we have run out of mappable virtual address space. }; /** @@ -49,6 +54,16 @@ namespace teachos::arch::context_switching::syscall uint64_t arg_5{}; ///< Sixth optional paramter to the syscall representing the R9 register. }; + /** + * @brief Response of a systemcall always containin an error code, signaling if the syscall even succeeded or not. + * Additionally it may contain up to 6 return values in the values struct. + */ + struct response + { + error error_code; ///< Error code returned by the syscall. If it failed all the values will be 0. + arguments values; ///< Optional return values of the syscall implementation. + }; + /** * @brief Calls the method associated with the given syscall number and passes the given optional arguments to it, * over the RDI, RSI, RDX, R10, R8 and R9 register. @@ -58,10 +73,12 @@ namespace teachos::arch::context_switching::syscall * @param args Optional arguments passable to the different syscall methods, called depending on the syscall_number. * Not passing the required parameters to the method, will result in passing 0 instead, which might make the fail or * not function correctly. - * @return Bool-convertable error code converting to true if the syscall failed or false if it didn't. + * @return The syscall implementation always returns a bool-convertable error code converting to true if the syscall + * failed or false if it didn't. Additionally it might pase additional values besides the error code, they will be set + * in the arguments struct. So the value can be read and used for further processing. */ [[gnu::section(".user_text")]] - auto syscall(type syscall_number, arguments args = {}) -> error; + auto syscall(type syscall_number, arguments args) -> response; } // namespace teachos::arch::context_switching::syscall 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 c50d2f6..cadec78 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 @@ -47,6 +47,15 @@ namespace teachos::arch::memory::heap */ [[gnu::section(".user_text")]] auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); } + /** + * @brief Special functionality fo the user heap allocator. Which will result in it being expanded by a syscall with + * addtionally 100 KiB, which are mapped into the page table. Will always work until there is no physical memory + * left. + * + * @return Start of the newly with syscall allocated free memory block. Nullptr if the syscall failed. + */ + [[gnu::section(".user_text")]] auto expand_heap_if_full() -> memory_block *; + /** * @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it. * -- cgit v1.2.3 From ef156dd6430855434b54275b22cd43ee3cedcfdc Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 11 May 2025 09:29:56 +0000 Subject: make frame_allocator and active_page_table statically available --- .../include/arch/memory/allocator/area_frame_allocator.hpp | 4 ++-- arch/x86_64/include/arch/memory/main.hpp | 14 ++++++++++++++ arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 3 +-- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp index 2244613..6cb5f56 100644 --- a/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/allocator/area_frame_allocator.hpp @@ -15,9 +15,9 @@ namespace teachos::arch::memory::allocator struct area_frame_allocator { /** - * @brief Constructor + * @brief Constructor. * - * @param mem_info Structure containg all relevant information to map and allocate memory + * @param mem_info Structure containg all relevant information to map and allocate memory. */ area_frame_allocator(multiboot::memory_information const & mem_info); diff --git a/arch/x86_64/include/arch/memory/main.hpp b/arch/x86_64/include/arch/memory/main.hpp index 164abbc..d51815f 100644 --- a/arch/x86_64/include/arch/memory/main.hpp +++ b/arch/x86_64/include/arch/memory/main.hpp @@ -1,8 +1,22 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP +#include "arch/memory/paging/page_entry.hpp" + +#include + namespace teachos::arch::memory { + + /** + * @brief Maps a heap section to a page. + * + * @param heap_start Start-address of the heap. + * @param heap_size Size of the heap. + * @param additional_flags Additional flags to apply to the page entry. + */ + auto remap_heap(std::size_t heap_start, std::size_t heap_size, paging::entry::bitset additional_flags) -> void; + /** * @brief Initializes memory management. * 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 7321548..756eeb1 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -38,7 +38,7 @@ namespace teachos::arch::memory::paging * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because * remapping active kernel memory in the kernel wouldn't work. */ - auto remap_kernel() -> active_page_table & + auto remap_kernel() -> void { // Set Page Global Enable bit auto cr4 = kernel::cpu::read_control_register(kernel::cpu::control_register::CR4); @@ -57,7 +57,6 @@ namespace teachos::arch::memory::paging auto const old_level_4_page = virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); active_table.unmap_page(allocator, old_level_4_page); - return active_table; } private: -- cgit v1.2.3 From ee4c61f7313fedd23d01c69ea5036fa38ef6248a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 12 May 2025 08:50:12 +0000 Subject: Adjust user heap to lazy allocate heap --- .../include/arch/memory/heap/linked_list_allocator.hpp | 6 ++---- arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp | 12 +++--------- 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/include') 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 377533c..582b4af 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 @@ -111,10 +111,8 @@ namespace teachos::arch::memory::heap auto coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer, std::size_t size) -> void; - std::size_t heap_start; ///< Start of the allocatable heap area. - std::size_t heap_end; ///< End of the allocatable heap area. - memory_block * first; ///< First free entry in our memory. - stl::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. + memory_block * first; ///< First free entry in our memory. + stl::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 cadec78..9c04718 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 @@ -14,12 +14,8 @@ namespace teachos::arch::memory::heap { /** * @brief Constructor. - * - * @param heap_start Start of the allocatable heap area - * @param heap_end End of the allocatable heap area (Start + Size) */ - [[gnu::section(".user_text")]] - user_heap_allocator(std::size_t heap_start, std::size_t heap_end); + user_heap_allocator() = default; /** * @copybrief heap_allocator::allocate @@ -126,10 +122,8 @@ namespace teachos::arch::memory::heap auto coalesce_free_memory_block(memory_block * previous_block, memory_block * current_block, void * pointer, std::size_t size) -> void; - std::size_t heap_start; ///< Start of the allocatable heap area. - std::size_t heap_end; ///< End of the allocatable heap area. - memory_block * first; ///< First free entry in our memory. - stl::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. + memory_block * first = {}; ///< First free entry in our memory. + stl::mutex mutex = {}; ///< Mutex to ensure only one thread calls allocate or deallocate at once. }; } // namespace teachos::arch::memory::heap -- cgit v1.2.3 From 29e067867e7a437d12351b481024d4bab431b202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 12 May 2025 13:51:12 +0000 Subject: Fix crashes because of are frame allocator copy --- arch/x86_64/include/arch/context_switching/syscall/main.hpp | 6 +++--- arch/x86_64/include/arch/memory/heap/memory_block.hpp | 2 ++ arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index 8587ab2..9d61f97 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -60,8 +60,8 @@ namespace teachos::arch::context_switching::syscall */ struct response { - error error_code; ///< Error code returned by the syscall. If it failed all the values will be 0. - arguments values; ///< Optional return values of the syscall implementation. + error error_code; ///< Error code returned by the syscall. If it failed all the values will be 0. + arguments values = {}; ///< Optional return values of the syscall implementation. }; /** @@ -78,7 +78,7 @@ namespace teachos::arch::context_switching::syscall * in the arguments struct. So the value can be read and used for further processing. */ [[gnu::section(".user_text")]] - auto syscall(type syscall_number, arguments args) -> response; + auto syscall(type syscall_number, arguments args = {}) -> response; } // namespace teachos::arch::context_switching::syscall diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp index e1cd288..9d1fb02 100644 --- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp +++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp @@ -18,6 +18,7 @@ namespace teachos::arch::memory::heap * @param size Amount of free memory of this specific hole. * @param next Optional pointer to the next free memory. */ + [[gnu::section(".user_text")]] memory_block(std::size_t size, memory_block * next); /** @@ -26,6 +27,7 @@ namespace teachos::arch::memory::heap * @note Used so the memory can be reused to construct other classes into, without having the old values. * Required because we cannot call delete, because it causes "undefined reference to `sbrk`". */ + [[gnu::section(".user_text")]] ~memory_block(); std::size_t size; ///< Amount of free memory this hole contains, has to always be atleast 16 bytes to hold the 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 756eeb1..ca7e2f9 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -45,7 +45,7 @@ namespace teachos::arch::memory::paging kernel::cpu::write_control_register(kernel::cpu::control_register::CR4, cr4 | 0x80); temporary_page temporary_page{virtual_page{0xCAFEBABE}, allocator}; - auto & active_table = active_page_table::create_or_get(); + decltype(auto) active_table = active_page_table::create_or_get(); auto const frame = allocator.allocate_frame(); exception_handling::assert(frame.has_value(), "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); -- cgit v1.2.3 From d4cc546df6eba2dd287785f1a63fbcce4a1b9bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 16 May 2025 09:58:57 +0000 Subject: Attempt to move atomic into stl text as well --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/include') 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 ca7e2f9..94c937d 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -144,24 +144,24 @@ namespace teachos::arch::memory::paging // Required to be accessible in User Mode: // - .boot_rodata (Contains constant data stored in ROM) // - .boot_bss (Contains statically allocated variables) - // - .user_text (Contains the actual code executed) + // - .user_text (Contains the actual user code executed) // - .user_data (Contains static user variables) - // - .stl_text (Contains code for custom std implementations) + // - .stl_text (Contains code for custom std implementations and standard library code) if (section.physical_address == 0x100000 /* .boot_rodata */ || section.physical_address == 0x102000 /* .boot_bss */ || - section.physical_address == 0x218000 /* .stl_text */) + section.physical_address == 0x209000 /* .stl_text */) { entry.set_user_accessible(); entry.set_global(); } - // TODO: We should be able to remove this somehow - if (section.physical_address == 0x209000 /* .text */) + // TODO: Can be removed once stl has been completly mapped into stl text + if (section.physical_address == 0x20A000 /* .text */) { entry.set_user_accessible(); } - if (section.physical_address == 0x217000 /* .user_text */ || + if (section.physical_address == 0x218000 /* .user_text */ || section.physical_address == 0x21E000 /* .user_data */) { entry.set_user_accessible(); -- cgit v1.2.3 From 5c314eef566df2732973e8cb35974ec49748adba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 16 May 2025 13:27:16 +0000 Subject: Fix bug where level 4 to level 2 entries are not mapped user accesible. --- arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp | 3 +++ arch/x86_64/include/arch/memory/paging/active_page_table.hpp | 5 +---- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 5 +---- arch/x86_64/include/arch/memory/paging/page_entry.hpp | 2 -- arch/x86_64/include/arch/memory/paging/page_table.hpp | 11 +++++++++-- 5 files changed, 14 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') 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 9c04718..42af23f 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 @@ -32,6 +32,9 @@ namespace teachos::arch::memory::heap [[gnu::section(".user_text")]] auto allocate(std::size_t size) -> void *; + /** + * @copybrief heap_allocator::deallocate + */ [[gnu::section(".user_text")]] auto deallocate(void * pointer) noexcept -> void; diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index d77b76c..f68d8b6 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -82,10 +82,7 @@ namespace teachos::arch::memory::paging for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level) { - // Ignore all bits passed besides the entry::USER_ACCESSIBLE bit, because for the entry into the Level 4 up to - // Level 2 page, we always have to set the entry::PRESENT and entry::WRITABLE bit anyway. - current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level), - flags.to_ulong() & entry::USER_ACCESSIBLE); + current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level), flags); } auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)]; 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 94c937d..5bf14fb 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -142,17 +142,14 @@ namespace teachos::arch::memory::paging entry entry{section.flags}; // Required to be accessible in User Mode: - // - .boot_rodata (Contains constant data stored in ROM) // - .boot_bss (Contains statically allocated variables) // - .user_text (Contains the actual user code executed) // - .user_data (Contains static user variables) // - .stl_text (Contains code for custom std implementations and standard library code) - if (section.physical_address == 0x100000 /* .boot_rodata */ || - section.physical_address == 0x102000 /* .boot_bss */ || + if (section.physical_address == 0x102000 /* .boot_bss */ || section.physical_address == 0x209000 /* .stl_text */) { entry.set_user_accessible(); - entry.set_global(); } // TODO: Can be removed once stl has been completly mapped into stl text diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp index 03cdb1a..8147c5c 100644 --- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp @@ -77,8 +77,6 @@ namespace teachos::arch::memory::paging */ auto set_user_accessible() -> void; - auto set_global() -> void; - /** * @brief Calculates the physical frame this entry is pointing too, can be null if the page is not present in * memory. diff --git a/arch/x86_64/include/arch/memory/paging/page_table.hpp b/arch/x86_64/include/arch/memory/paging/page_table.hpp index 7b7e29e..b972337 100644 --- a/arch/x86_64/include/arch/memory/paging/page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/page_table.hpp @@ -95,13 +95,20 @@ namespace teachos::arch::memory::paging { auto const allocated_frame = allocator.allocate_frame(); exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); - this->operator[](table_index) - .set_entry(allocated_frame.value(), flags.to_ulong() | entry::PRESENT | entry::WRITABLE); + this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); // There should now be an entry at the previously not existent index, therefore we can simply access it again. next_handle = next_table(table_index); exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); next_handle.value().zero_entries(); } + + // Check if the now created or previously created level 4, level 3 or level 2 page entry is used by user + // accessible code. If it is that page entry needs to be user accesible as well. + entry entry{flags.to_ulong()}; + if (entry.contains_flags(entry::USER_ACCESSIBLE)) + { + this->operator[](table_index).set_user_accessible(); + } return next_handle.value(); } -- cgit v1.2.3 From 1b5a771a34743a2973a82de5ebdfd22da030b841 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 18 May 2025 13:21:42 +0000 Subject: update linker file and improve section parsing --- .../include/arch/memory/paging/kernel_mapper.hpp | 28 ++++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'arch/x86_64/include') 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 5bf14fb..977b40d 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -7,6 +7,9 @@ #include "arch/memory/paging/temporary_page.hpp" #include "arch/video/vga/text.hpp" +#include +#include + namespace teachos::arch::memory::paging { /** @@ -142,24 +145,17 @@ namespace teachos::arch::memory::paging entry entry{section.flags}; // Required to be accessible in User Mode: - // - .boot_bss (Contains statically allocated variables) - // - .user_text (Contains the actual user code executed) - // - .user_data (Contains static user variables) - // - .stl_text (Contains code for custom std implementations and standard library code) - if (section.physical_address == 0x102000 /* .boot_bss */ || - section.physical_address == 0x209000 /* .stl_text */) - { - entry.set_user_accessible(); - } + constexpr std::array 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) + 0x21E000, // .user_data (Contains static user variables) - // TODO: Can be removed once stl has been completly mapped into stl text - if (section.physical_address == 0x20A000 /* .text */) - { - entry.set_user_accessible(); - } + 0x20A000 // .text (Necessary, because symbols for standard library are placed there) + }; - if (section.physical_address == 0x218000 /* .user_text */ || - section.physical_address == 0x21E000 /* .user_data */) + if (std::find(user_section_bases.begin(), user_section_bases.end(), section.physical_address) != + user_section_bases.end()) { entry.set_user_accessible(); } -- cgit v1.2.3 From 8d39f3f67734bf39cada370c39243e6ef33bf4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 18 May 2025 14:45:05 +0000 Subject: Make new usable for both kernel and user calls --- .../interrupt_descriptor_table/segment_selector.hpp | 8 ++++++++ arch/x86_64/include/arch/context_switching/syscall/main.hpp | 3 +++ arch/x86_64/include/arch/kernel/cpu/segment_register.hpp | 1 + arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp | 6 ++++++ 4 files changed, 18 insertions(+) (limited to 'arch/x86_64/include') 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 5be449f..82719bc 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 @@ -66,6 +66,14 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table */ auto contains_flags(std::bitset<3U> other) const -> bool; + /** + * @brief Gets the index into the global descriptor table this segment selector is pointing too. + * + * @return Underlying value of the index field, bit 3 - 16. + */ + [[gnu::section(".user_text")]] + auto get_index() const -> uint16_t; + /** * @brief Defaulted three-way comparsion operator. */ diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index 9d61f97..e391c1f 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -19,6 +19,9 @@ namespace teachos::arch::context_switching::syscall /// parameters and uses them as out parameters instead, where arg_0 is the start of the newly /// mapped heap area and arg_1 is the size of the entire area. Can be less than 100 KiB if less /// space remains. + ASSERT = 3U, /// Loads the arg_0 parameter as a boolean which needs to be true or it will print the message in + /// arg_1 parameter onto the VGA buffer screen, keep it as a nullptr if it shouldn't print anything + /// and then it halts the further execution of the application. }; /** diff --git a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp index 36ada23..a236452 100644 --- a/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/segment_register.hpp @@ -31,6 +31,7 @@ namespace teachos::arch::kernel::cpu * * @return Segment Selector pointing to the currently loaded Code Segment. */ + [[gnu::section(".user_text")]] auto read_code_segment_register() -> context_switching::interrupt_descriptor_table::segment_selector; /** diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index 6fcab6f..c98c130 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -97,16 +97,22 @@ namespace teachos::arch::memory::heap }; } // namespace teachos::arch::memory::heap +[[gnu::section(".user_text")]] auto operator new(std::size_t size) -> void *; +[[gnu::section(".user_text")]] auto operator delete(void * pointer) noexcept -> void; +[[gnu::section(".user_text")]] auto operator delete(void * pointer, std::size_t size) noexcept -> void; +[[gnu::section(".user_text")]] auto operator new[](std::size_t size) -> void *; +[[gnu::section(".user_text")]] auto operator delete[](void * pointer) noexcept -> void; +[[gnu::section(".user_text")]] auto operator delete[](void * pointer, std::size_t size) noexcept -> void; #endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP -- cgit v1.2.3 From 8a6a9a3a159ce1b960721eb921b8e8d81b15b718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 20 May 2025 12:29:09 +0000 Subject: Improve syscalls and user heap allocator --- .../include/arch/memory/heap/user_heap_allocator.hpp | 15 +++++++++++++++ .../include/arch/memory/paging/kernel_mapper.hpp | 20 ++++++++------------ 2 files changed, 23 insertions(+), 12 deletions(-) (limited to 'arch/x86_64/include') 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 42af23f..6b1b7bb 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 @@ -4,6 +4,8 @@ #include "arch/memory/heap/memory_block.hpp" #include "arch/stl/mutex.hpp" +#include + namespace teachos::arch::memory::heap { /** @@ -46,6 +48,19 @@ namespace teachos::arch::memory::heap */ [[gnu::section(".user_text")]] auto constexpr min_allocatable_size() -> std::size_t { return sizeof(memory_block); } + /** + * @brief Checks if the given memory block is big enough and if it is allocates into the current block. + * + * @note Adjusts the link of the previous memory block to the new smaller remaining block. If the allocation used + * the complete block instead the previous block will point to the next block of the current memroy block that was + * used for the allocation. + * + * @return Allocated usable memory area. + */ + [[gnu::section(".user_text")]] auto + allocate_into_memory_block_if_big_enough(memory_block * current, memory_block * previous, std::size_t total_size) + -> std::optional; + /** * @brief Special functionality fo the user heap allocator. Which will result in it being expanded by a syscall with * addtionally 100 KiB, which are mapped into the page table. Will always work until there is no physical memory 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 977b40d..b211b8b 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -124,6 +124,13 @@ namespace teachos::arch::memory::paging auto map_elf_kernel_sections(active_page_table & active_table) -> void { exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); + 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) + }; + for (auto const & section : mem_info.sections) { if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) @@ -144,18 +151,7 @@ namespace teachos::arch::memory::paging allocator::frame_container const frames{begin, end}; entry entry{section.flags}; - // Required to be accessible in User Mode: - constexpr std::array 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) - 0x21E000, // .user_data (Contains static user variables) - - 0x20A000 // .text (Necessary, because symbols for standard library are placed there) - }; - - if (std::find(user_section_bases.begin(), user_section_bases.end(), section.physical_address) != - user_section_bases.end()) + if (std::ranges::find(USER_SECTION_BASES, section.physical_address) != USER_SECTION_BASES.end()) { entry.set_user_accessible(); } -- cgit v1.2.3 From 3e597ede8079883b3b9d48faf94b8a7bec2a2118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 27 May 2025 12:41:50 +0000 Subject: Readd text kernels ection with explanation --- arch/x86_64/include/arch/context_switching/syscall/main.hpp | 2 +- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/syscall/main.hpp b/arch/x86_64/include/arch/context_switching/syscall/main.hpp index e391c1f..59adc13 100644 --- a/arch/x86_64/include/arch/context_switching/syscall/main.hpp +++ b/arch/x86_64/include/arch/context_switching/syscall/main.hpp @@ -28,7 +28,7 @@ namespace teachos::arch::context_switching::syscall * @brief Possible error codes that can be returned by the different syscall methods called depending on the type * enum. */ - enum class error + enum class error : uint8_t { OK = 0U, ///< No error occured in syscall. OUT_OF_MEMORY = 1U, ///< Expanding heap failed because we have run out of mappable virtual address space. 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 b211b8b..81ac0cb 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -129,6 +129,9 @@ namespace teachos::arch::memory::paging 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) + + 0x20A000 // .text (Necessary, because symbols for all template standard library features are placed here if + // they were first used in the Kernel Code Section) }; for (auto const & section : mem_info.sections) -- cgit v1.2.3 From 9f2e780030e2101d5f7f01f42df805db9a5fa809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 30 May 2025 12:48:57 +0000 Subject: Clean up files --- .../memory/allocator/stack_frame_allocator.hpp | 67 ---------------------- 1 file changed, 67 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp b/arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp deleted file mode 100644 index a8e7233..0000000 --- a/arch/x86_64/include/arch/memory/allocator/stack_frame_allocator.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_STACK_FRAME_ALLOCATOR_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_STACK_FRAME_ALLOCATOR_HPP - -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/multiboot/reader.hpp" -#include "arch/stl/stack.hpp" - -#include - -namespace teachos::arch::memory::allocator -{ - /** - * @brief Uses an internal stack-like dynamic structure to keep track of the address of all avaialable physical frames - * that are available using the memory areas read from the multiboot2 information pointer and simply pushes - * deallocated frames back onto the stack. Allows for constant speed O(1) allocation and deallocation - */ - struct stack_frame_allocator - { - /** - * @brief Constructor - * - * @param mem_info Structure containg all relevant information to map and allocate memory - */ - stack_frame_allocator(multiboot::memory_information const & mem_info); - - /** - * @brief Allocate memory by finding and returning a free physical frame. - * - * @return next free physical frame or nullopt if none was found. - */ - auto allocate_frame() -> std::optional; - - /** - * @brief Deallocates a previously allocated physical frame. - * - * @param physical_frame Previously allocated physical_frame that should be deallocated. - */ - auto deallocate_frame(physical_frame const & physical_frame) -> void; - - private: - /** - * @brief Load all initally free physical frames from the current memory area into the underlying stack data - * structure so they can simply be accessed once required. Recallling the method will load all free physical frames - * from the next free memory area until there are no memory areas left. - */ - auto load_free_physical_frames() -> void; - - /** - * @brief Find the next memory area and write it into current_area. - */ - auto choose_next_area() -> void; - - stl::stack free_frames; ///< All currently free physical frames in a LIFO (last-in, first-out) - ///< data structure. - physical_frame next_free_frame; ///< The physical_frame after the last allocated one. - std::optional current_area; ///< The current memory area. - multiboot::memory_area_container const - memory_areas; ///< All memory areas in custom container allows to use std::ranges. - physical_frame const kernel_start; ///< The start address of the kernel code in memory. - physical_frame const kernel_end; ///< The end address of the kernel code in memory. - physical_frame const multiboot_start; ///< The start address of the multiboot code in memory. - physical_frame const multiboot_end; ///< The end address of the multiboot code in memory. - }; - -} // namespace teachos::arch::memory::allocator - -#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_STACK_FRAME_ALLOCATOR_HPP -- cgit v1.2.3 From 1031a69ca5e23f2087148ad57e57506735872617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 4 Jun 2025 14:48:50 +0000 Subject: Adjust minor comments --- .../interrupt_descriptor_table/gate_descriptor.hpp | 2 +- .../context_switching/interrupt_descriptor_table/idt_flags.hpp | 6 +++--- .../interrupt_descriptor_table/ist_offset.hpp | 10 ++++++---- .../interrupt_descriptor_table/segment_selector.hpp | 5 +++-- .../context_switching/segment_descriptor_table/access_byte.hpp | 2 +- .../context_switching/segment_descriptor_table/gdt_flags.hpp | 2 +- .../arch/interrupt_handling/generic_interrupt_handler.hpp | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) (limited to 'arch/x86_64/include') diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp index 22cd0f0..07110c8 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp @@ -30,7 +30,7 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table * field that has to be used, because the 64-bit gate descriptor needs to be big enough for two 32-bit gate * descriptor. * - 16 bit Segment Selector - * - 3 bit IST + * - 3 bit Interrupt Stack Table Offset * - 8 bit Type and Flags * - 64 bit Offset * diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp index 948f478..5104c36 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp @@ -14,7 +14,7 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table struct [[gnu::packed]] idt_flags { /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + * @brief Possible set bits in our underlying bits and the meaning when they are set. */ enum bitset : uint8_t { @@ -59,10 +59,10 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table auto contains_flags(std::bitset<8U> other) const -> bool; /** - * @brief Allows to compare the underlying std::bitset of two instances. + * @brief Allows to compare the underlying bits of two instances. * * @param other Other instance that we want to compare with. - * @return Whether the underlying std::bitset of both types is the same. + * @return Whether the underlying set bits of both types are the same. */ auto operator==(idt_flags const & other) const -> bool = default; diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp index cefe1b2..e45bcf4 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp @@ -7,7 +7,7 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { /** - * @brief Defines helper function for all states that the ist field of a gate descriptor can + * @brief Defines helper function for all states that the interrupt stack table offset field of a gate descriptor can * have. Is automatically increased to one byte in size, to include the following 5 reserved bits in the gate * descriptor. */ @@ -21,9 +21,11 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table /** * @brief Constructor. * - * @param index Index into local or global descriptor table. + * @param offset Offset into the interrupt stack table. A value of of 0 means we do not switch stacks, whereas 1 - 7 + * mean we switch to the n-th stack in the Interrupt Stack Table, contained in the TSS if the gate descriptor that + * contains this field is called. */ - ist_offset(uint8_t index); + ist_offset(uint8_t offset); /** * @brief Allows to compare the underlying set bits of two instances. @@ -34,7 +36,7 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table auto operator==(ist_offset const & other) const -> bool = default; private: - uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. A value of of 0 menas we do not switch stacks, + uint8_t _ist : 3 = {}; ///< Offset into the interrupt stack table. A value of of 0 means we do not switch stacks, ///< whereas 1 - 7 mean we switch to the n-th stack in the Interrupt Stack Table, contained ///< in the TSS if the gate descriptor that contains this field is called. }; 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 82719bc..2a7704e 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 @@ -17,7 +17,7 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table struct [[gnu::packed]] segment_selector { /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + * @brief Possible set bits in our underlying bits and the meaning when they are set. */ enum bitset : uint8_t { @@ -67,7 +67,8 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table auto contains_flags(std::bitset<3U> other) const -> bool; /** - * @brief Gets the index into the global descriptor table this segment selector is pointing too. + * @brief Gets the index into the global descriptor table or the local descriptor table this segment selector is + * pointing too. * * @return Underlying value of the index field, bit 3 - 16. */ diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp index 621b570..7450330 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp @@ -14,7 +14,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table struct [[gnu::packed]] access_byte { /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + * @brief Possible set bits in our underlying bits and the meaning when they are set. */ enum bitset : uint8_t { diff --git a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp index 4b84035..e24b988 100644 --- a/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp +++ b/arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp @@ -14,7 +14,7 @@ namespace teachos::arch::context_switching::segment_descriptor_table struct [[gnu::packed]] gdt_flags { /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. + * @brief Possible set bits in our underlying bits and the meaning when they are set. */ enum bitset : uint8_t { diff --git a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp index 2d26668..15b35c1 100644 --- a/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp +++ b/arch/x86_64/include/arch/interrupt_handling/generic_interrupt_handler.hpp @@ -13,7 +13,7 @@ namespace teachos::arch::interrupt_handling */ struct [[gnu::packed]] interrupt_frame { - // uint64_t error_code; ///< Error code pushed by some exceptions. + // uint64_t error_code; ///< Error code only pushed by some exceptions, therefore it is commented out. uint64_t ip; ///< Instruction pointer at the time of the interrupt. uint64_t cs; ///< Code segment selector indicating privilege level. uint64_t flags; ///< CPU flags (RFLAGS) storing processor state. -- cgit v1.2.3