diff options
Diffstat (limited to 'src/gdt.h')
-rw-r--r-- | src/gdt.h | 52 |
1 files changed, 42 insertions, 10 deletions
@@ -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); |