aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2025-03-25 16:58:24 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2025-03-25 16:58:24 +0000
commit66fefaeb16bcbc4eae5ce5256ae76f51a155cded (patch)
tree121b05b3764c7825f4f87c43e0bce6dd32707d29 /arch/x86_64
parentccb47845d99e098c183f596cd1a3eb1db5c676da (diff)
downloadkernel-66fefaeb16bcbc4eae5ce5256ae76f51a155cded.tar.xz
kernel-66fefaeb16bcbc4eae5ce5256ae76f51a155cded.zip
Implement idtr structure and document possible flags.
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/CMakeLists.txt7
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/gate_descriptor.hpp54
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/idt_flags.hpp74
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp14
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.hpp4
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/ist_offset.hpp41
-rw-r--r--arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp74
-rw-r--r--arch/x86_64/include/arch/context_switching/main.hpp3
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/access_byte.hpp14
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/gdt_flags.hpp4
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp36
-rw-r--r--arch/x86_64/include/arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp2
-rw-r--r--arch/x86_64/include/arch/kernel/cpu/ss.hpp39
-rw-r--r--arch/x86_64/include/arch/memory/allocator/physical_frame.hpp4
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp2
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/memory_map.hpp2
-rw-r--r--arch/x86_64/include/arch/memory/paging/virtual_page.hpp4
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp19
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp15
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp24
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp10
-rw-r--r--arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp16
-rw-r--r--arch/x86_64/src/context_switching/main.cpp7
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp105
-rw-r--r--arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp10
-rw-r--r--arch/x86_64/src/kernel/cpu/ss.cpp29
26 files changed, 425 insertions, 188 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index cf92feb..5242f3d 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -94,13 +94,16 @@ target_sources("_exception" PRIVATE
target_sources("_context" PRIVATE
"src/context_switching/segment_descriptor_table/access_byte.cpp"
"src/context_switching/segment_descriptor_table/gdt_flags.cpp"
- "src/context_switching/segment_descriptor_table/global_descriptor_table.cpp"
"src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp"
+ "src/context_switching/segment_descriptor_table/global_descriptor_table.cpp"
"src/context_switching/segment_descriptor_table/segment_descriptor.cpp"
"src/context_switching/main.cpp"
"src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp"
- "src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp"
+ "src/context_switching/interrupt_descriptor_table/idt_flags.cpp"
"src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table_pointer.cpp"
+ "src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp"
+ "src/context_switching/interrupt_descriptor_table/ist_offset.cpp"
+ "src/context_switching/interrupt_descriptor_table/segment_selector.cpp"
)
#[============================================================================[
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 <bitset>
+#include <cstdint>
+
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 <bitset>
+#include <cstdint>
+
+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 <cstdint>
-
namespace teachos::arch::context_switching::interrupt_descriptor_table
{
- typedef stl::vector<gate_descriptor> interrupt_descriptor_table;
+ using interrupt_descriptor_table = stl::vector<gate_descriptor>;
/**
* @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 <bitset>
+#include <cstdint>
+
+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 <bitset>
+#include <cstdint>
+
+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<segment_descriptor> global_descriptor_table;
+ using global_descriptor_table = stl::vector<segment_descriptor>;
/**
* @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 <bitset>
#include <cstdint>
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<stl::forward_value_iterator<physical_frame>> frame_container;
+ using frame_container = stl::container<stl::forward_value_iterator<physical_frame>>;
} // 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<stl::contiguous_pointer_iterator<elf_section_header>> elf_section_header_container;
+ using elf_section_header_container = stl::container<stl::contiguous_pointer_iterator<elf_section_header>>;
} // 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<stl::contiguous_pointer_iterator<memory_area>> memory_area_container;
+ using memory_area_container = stl::container<stl::contiguous_pointer_iterator<memory_area>>;
} // 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<stl::forward_value_iterator<virtual_page>> page_container;
+ using page_container = stl::container<stl::forward_value_iterator<virtual_page>>;
} // namespace teachos::arch::memory::paging
diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp
index 4f18197..28f289c 100644
--- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp
+++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/gate_descriptor.cpp
@@ -2,4 +2,23 @@
namespace teachos::arch::context_switching::interrupt_descriptor_table
{
+ gate_descriptor::gate_descriptor(uint128_t flags)
+ : _offset_1(flags)
+ , _selector(flags >> 19U, flags >> 16U)
+ , _ist(flags >> 32U)
+ , _flags(flags >> 40U)
+ , _offset_2(flags >> 48U)
+ {
+ // Nothing to do.
+ }
+
+ gate_descriptor::gate_descriptor(segment_selector selector, ist_offset ist, idt_flags flags, uint64_t offset)
+ : _offset_1(offset)
+ , _selector(selector)
+ , _ist(ist)
+ , _flags(flags)
+ , _offset_2(offset >> 16U)
+ {
+ // Nothing to do.
+ }
} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp
new file mode 100644
index 0000000..e7379ef
--- /dev/null
+++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp
@@ -0,0 +1,15 @@
+#include "arch/context_switching/interrupt_descriptor_table/idt_flags.hpp"
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ idt_flags::idt_flags(uint8_t flags)
+ : _flags(flags)
+ {
+ // Nothing to do.
+ }
+
+ auto idt_flags::contains_flags(std::bitset<8U> other) const -> bool
+ {
+ return (std::bitset<8U>{_flags} & other) == other;
+ }
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp
index 619a695..7346248 100644
--- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp
+++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp
@@ -1,10 +1,28 @@
#include "arch/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.hpp"
+#include "arch/exception_handling/assert.hpp"
+#include "arch/kernel/cpu/idtr.hpp"
+
namespace teachos::arch::context_switching::interrupt_descriptor_table
{
- auto initialize_interrupt_descriptor_table() -> void
+ namespace
{
- // DO NOT
- }
+ auto create_interrupt_descriptor_table() -> interrupt_descriptor_table { return interrupt_descriptor_table{}; }
+ } // namespace
+
+ auto initialize_interrupt_descriptor_table() -> interrupt_descriptor_table &
+ {
+ // Interrupt Descriptor Table needs to be kept alive
+ static auto idt = create_interrupt_descriptor_table();
+ interrupt_descriptor_table_pointer idt_pointer{static_cast<uint16_t>(idt.size() - 1), &idt};
+ kernel::cpu::load_interrupt_descriptor_table(idt_pointer);
+
+ auto const stored_gdt_pointer = kernel::cpu::store_interrupt_descriptor_table();
+ arch::exception_handling::assert(
+ idt_pointer == stored_gdt_pointer,
+ "[Interrupt Descriptor Table] Loaded IDTR value is not the same as the stored value.");
+
+ return idt;
+ }
} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp
new file mode 100644
index 0000000..a70e75d
--- /dev/null
+++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/ist_offset.cpp
@@ -0,0 +1,10 @@
+#include "arch/context_switching/interrupt_descriptor_table/ist_offset.hpp"
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ ist_offset::ist_offset(uint8_t index)
+ : _ist(index)
+ {
+ // Nothing to do.
+ }
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp
new file mode 100644
index 0000000..494e50f
--- /dev/null
+++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp
@@ -0,0 +1,16 @@
+#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp"
+
+namespace teachos::arch::context_switching::interrupt_descriptor_table
+{
+ segment_selector::segment_selector(uint16_t index, uint8_t flags)
+ : _flags(flags)
+ , _index(index)
+ {
+ // Nothing to do.
+ }
+
+ auto segment_selector::contains_flags(std::bitset<3U> other) const -> bool
+ {
+ return (std::bitset<3U>{_flags} & other) == other;
+ }
+} // namespace teachos::arch::context_switching::interrupt_descriptor_table
diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp
index b682e79..95a25e0 100644
--- a/arch/x86_64/src/context_switching/main.cpp
+++ b/arch/x86_64/src/context_switching/main.cpp
@@ -11,10 +11,7 @@ namespace teachos::arch::context_switching
auto initialize_descriptor_tables() -> descriptor_tables
{
decltype(auto) global_descriptor_table = segment_descriptor_table::initialize_global_descriptor_table();
-
- // TODO: Replace random construction with return value of initialization.
- interrupt_descriptor_table::interrupt_descriptor_table idt{};
- interrupt_descriptor_table::initialize_interrupt_descriptor_table();
+ decltype(auto) interrupt_descriptor_table = interrupt_descriptor_table::initialize_interrupt_descriptor_table();
kernel::cpu::jmp((uint64_t)&global_descriptor_table.at(1), boot::segment_register_reload_pointer);
@@ -30,7 +27,7 @@ namespace teachos::arch::context_switching
kernel::cpu::set_interrupt_flag();
- descriptor_tables tables = {global_descriptor_table, idt};
+ descriptor_tables tables = {global_descriptor_table, interrupt_descriptor_table};
return tables;
}
} // namespace teachos::arch::context_switching
diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp
index 1bbd24f..69cce19 100644
--- a/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp
+++ b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp
@@ -9,69 +9,66 @@
namespace teachos::arch::context_switching::segment_descriptor_table
{
- auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level)
- -> segment_descriptor
+ namespace
{
- uint8_t access_level_bitset = access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT;
- if (access_level == access_level::KERNEL)
- {
- access_level_bitset |= access_byte::ACCESS_LEVEL_KERNEL;
- }
- else if (access_level == access_level::USER)
- {
- access_level_bitset |= access_byte::ACCESS_LEVEL_USER;
- }
- uint8_t gdt_flags_bitset = gdt_flags::GRANULARITY;
- if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT)
+ auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_byte access_level)
+ -> segment_descriptor
{
- gdt_flags_bitset |= gdt_flags::LENGTH;
- access_level_bitset |= access_byte::CODE_SEGMENT | access_byte::READABLE;
+ uint8_t access_level_bits =
+ access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT | *reinterpret_cast<uint8_t *>(&access_level);
+ uint8_t gdt_flags_bits = gdt_flags::GRANULARITY;
+ if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT)
+ {
+ gdt_flags_bits |= gdt_flags::LENGTH;
+ access_level_bits |= access_byte::CODE_SEGMENT | access_byte::READABLE;
+ }
+ else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT)
+ {
+ gdt_flags_bits |= gdt_flags::UPPER_BOUND;
+ access_level_bits |= access_byte::WRITABLE;
+ }
+
+ uint64_t const base = 0x0;
+ std::bitset<20U> const limit{0xFFFFF};
+ access_byte const access_byte{access_level_bits};
+ gdt_flags const gdt_flags{gdt_flags_bits, limit};
+ segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit};
+ return segment_descriptor;
}
- else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT)
+
+ auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor
{
- gdt_flags_bitset |= gdt_flags::UPPER_BOUND;
- access_level_bitset |= access_byte::WRITABLE;
+ constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1;
+ access_byte const tss_access_byte{access_byte::PRESENT | access_byte::DESCRIPTOR_LEVEL_KERNEL |
+ access_byte::TASK_STATE_SEGMENT_AVAILABLE};
+ gdt_flags const tss_gdt_flags{0U, TSS_LIMIT};
+ segment_descriptor const tss_descriptor{tss_access_byte, tss_gdt_flags, reinterpret_cast<uint64_t>(tss),
+ TSS_LIMIT};
+ return tss_descriptor;
}
- uint64_t const base = 0x0;
- std::bitset<20U> const limit{0xFFFFF};
- access_byte const access_byte{access_level_bitset};
- gdt_flags const gdt_flags{gdt_flags_bitset, limit};
- segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit};
- return segment_descriptor;
- }
-
- auto create_global_descriptor_table() -> global_descriptor_table
- {
- segment_descriptor const null_segment{0};
- segment_descriptor const kernel_code_segment =
- create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::KERNEL);
- segment_descriptor const kernel_data_segment =
- create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::KERNEL);
- segment_descriptor const user_code_segment =
- create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER);
- segment_descriptor const user_data_segment =
- create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::USER);
-
- // Task State Segment needs to be kept alive
- static auto tss = new task_state_segment();
- segment_descriptor const tss_descriptor = create_task_state_segment_descriptor(tss);
+ auto create_global_descriptor_table() -> global_descriptor_table
+ {
+ segment_descriptor const null_segment{0};
+ segment_descriptor const kernel_code_segment =
+ create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL);
+ segment_descriptor const kernel_data_segment =
+ create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL);
+ segment_descriptor const user_code_segment =
+ create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER);
+ segment_descriptor const user_data_segment =
+ create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER);
- global_descriptor_table const global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment,
- user_code_segment, user_data_segment, tss_descriptor};
- return global_descriptor_table;
- }
+ // Task State Segment needs to be kept alive
+ static auto tss = new task_state_segment();
+ segment_descriptor const tss_descriptor = create_task_state_segment_descriptor(tss);
- auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor
- {
- constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1;
- access_byte const tss_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL |
- access_byte::TASK_STATE_SEGMENT_AVAILABLE};
- gdt_flags const tss_gdt_flags{0U, TSS_LIMIT};
- segment_descriptor const tss_descriptor{tss_access_byte, tss_gdt_flags, reinterpret_cast<uint64_t>(tss), TSS_LIMIT};
- return tss_descriptor;
- }
+ global_descriptor_table const global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment,
+ user_code_segment, user_data_segment, tss_descriptor};
+ return global_descriptor_table;
+ }
+ } // namespace
auto initialize_global_descriptor_table() -> global_descriptor_table &
{
diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp
index 6d831a1..74f93b2 100644
--- a/arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp
+++ b/arch/x86_64/src/context_switching/segment_descriptor_table/segment_descriptor.cpp
@@ -3,11 +3,11 @@
namespace teachos::arch::context_switching::segment_descriptor_table
{
segment_descriptor::segment_descriptor(uint128_t flags)
- : _limit_1(flags << 112U)
- , _base_1((flags >> 16U) << 88U)
- , _access((flags >> 40U) << 80U)
- , _flag((flags >> 52U) << 72U, (flags >> 48U) << 72U)
- , _base_2((flags >> 56U) << 32U)
+ : _limit_1(flags)
+ , _base_1(flags >> 16U)
+ , _access(flags >> 40U)
+ , _flag(flags >> 52U, flags >> 48U)
+ , _base_2(flags >> 56U)
{
// Nothing to do.
}
diff --git a/arch/x86_64/src/kernel/cpu/ss.cpp b/arch/x86_64/src/kernel/cpu/ss.cpp
index 1f28e7f..0978eca 100644
--- a/arch/x86_64/src/kernel/cpu/ss.cpp
+++ b/arch/x86_64/src/kernel/cpu/ss.cpp
@@ -2,32 +2,15 @@
namespace teachos::arch::kernel::cpu
{
- segment_selector::segment_selector(uint16_t index, std::bitset<1U> table_indicator,
- std::bitset<2U> requested_privilege_level)
- : index(index)
- , table_indicator(table_indicator)
- , requested_privilege_level(requested_privilege_level)
+ auto read_ss() -> context_switching::interrupt_descriptor_table::segment_selector
{
- // Nothing to do
- }
-
- auto segment_selector::to_uint16() const -> uint16_t
- {
- return static_cast<uint16_t>((index << 3) | (table_indicator.to_ulong() << 2) |
- requested_privilege_level.to_ulong());
- }
-
- auto read_ss() -> uint16_t
- {
- uint16_t segment_selector;
- asm volatile("mov %%ss, %[output]" : [output] "=r"(segment_selector));
+ context_switching::interrupt_descriptor_table::segment_selector segment_selector{};
+ asm volatile("mov %%ss, %[output]" : [output] "=m"(segment_selector));
return segment_selector;
}
- auto write_ss(segment_selector selector) -> void
+ auto write_ss(context_switching::interrupt_descriptor_table::segment_selector selector) -> void
{
- uint16_t ss = selector.to_uint16();
- asm volatile("mov %[input], %%ss" : /* no output from call */ : [input] "r"(ss));
+ asm volatile("mov %[input], %%ss" : /* no output from call */ : [input] "m"(selector));
}
-
-} // namespace teachos::arch::kernel::cpu \ No newline at end of file
+} // namespace teachos::arch::kernel::cpu