aboutsummaryrefslogtreecommitdiff
path: root/src/gdt.h
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-02-09 17:39:08 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-02-09 17:39:08 +0200
commitc6e0d58e177d91f01b6de80073d066bf03de2913 (patch)
treee23139d87da7967e36517fe869b3677e3a4bc9c3 /src/gdt.h
parentLoading GDT (diff)
downloadkernel.cpp-c6e0d58e177d91f01b6de80073d066bf03de2913.tar.xz
Add more comments to GDT code
Diffstat (limited to 'src/gdt.h')
-rw-r--r--src/gdt.h52
1 files changed, 42 insertions, 10 deletions
diff --git a/src/gdt.h b/src/gdt.h
index 99a6da2..244908b 100644
--- a/src/gdt.h
+++ b/src/gdt.h
@@ -33,15 +33,37 @@ public:
class SegmentDescriptor {
public:
- SegmentDescriptor(uint32_t base = 0, uint32_t limit = 0, uint8_t type = 0);
+ enum Ring : unsigned int { Ring0 = 0x0, Ring1 = 0x1, Ring2 = 0x2, Ring3 = 0x3 };
+ struct Access {
+ bool accessed : 1 = false; // if 0, is set by processor when accessed
+ bool r_w : 1 = false; // on code segment: read toggle
+ // on data segment: write toggle
+ bool direction_conforming : 1 = false; // TODO
+ bool exe : 1 = false; // true for code segment, false for data segment
+ bool segment : 1 = false; // segment bit: 1 for code/data segments
+ // 0 for gates and tss
+ Ring privilege : 2 = Ring0; // descriptor privilege level
+ bool present : 1 = true; // must be 1 for every active segment
+ } __attribute__((packed));
+
+ SegmentDescriptor() { access.present = false; };
+
+ template <uint32_t limit>
+ static SegmentDescriptor make(uint32_t base, Access a) {
+ static_assert(limit <= 0xffffu || (limit & 0xfff) == 0xfff);
+ return SegmentDescriptor(base, limit, a);
+ }
+
[[nodiscard]] uint32_t base() const;
[[nodiscard]] uint32_t limit() const;
private:
+ SegmentDescriptor(uint32_t base, uint32_t limit, Access a);
+
/*
- * |31| | | | | | |24|23|22| |20|19| | |16|15| | |12|11| | | 8| 7| | | | | | | 0|
- * | base (24~31) | G|DB| | A| lim(16~19)| P| DPL | S| Type | base (16~23) |
- * | base (0~15) | limit (0~15) |
+ * |31| | | | | | |24|23|22|21|20|19| | |16|15| | |12|11| | | 8| 7| | | | | | | 0|
+ * | base_31_24 | G|DB| | A| lim_19_16 | P| DPL | S| Type | base_23_16 |
+ * | base_15_0 | limit_15_0 |
* |31| | | | | | | | | | | | | | |16|15| | | | | | | | | | | | | | | 0|
*
* limit size of segment - 1, either in bytes or in 4KiB chunks (check flags)
@@ -50,12 +72,21 @@ public:
* flags defines the segment chunks and 16/32 bit
*/
- uint16_t limit_low;
- uint16_t base_low;
- uint8_t base_high;
- uint8_t type;
- uint8_t flags_limit_high;
- uint8_t base_vhigh;
+ unsigned int limit_15_0 : 16 = 0; // low bits of segment limit
+ unsigned int base_15_0 : 16 = 0; // low bits of segment base address
+ unsigned int base_23_16 : 8 = 0; // middle bits of segment base address
+
+ /* access byte */
+ Access access;
+
+ unsigned int limit_19_16 : 4 = 0; // high bits of segment limit
+ /* flags */
+ [[maybe_unused]] unsigned int a : 1 = 0; // unused, available for software use
+ [[maybe_unused]] unsigned int rsv : 1 = 0; // reserved
+ unsigned int db : 1 = 0; // 0: 16-bit segment; 1: 32-bit segment
+ unsigned int granularity : 1 = 0; // limit scaled by 4k when set
+
+ unsigned int base_31_24 : 8 = 0; // high bits of segment address
} __attribute__((packed));
private:
@@ -64,3 +95,4 @@ private:
static_assert(sizeof(GDT::Pointer) == 6);
static_assert(sizeof(GDT::SegmentDescriptor) == 8);
+static_assert(sizeof(GDT::SegmentDescriptor::Access) == 1);