diff --git a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp index 3db245f..4542472 100644 --- a/Architecture/amd64/cpu/GlobalDescriptorTable.cpp +++ b/Architecture/amd64/cpu/GlobalDescriptorTable.cpp @@ -25,117 +25,84 @@ namespace GlobalDescriptorTable { static GlobalDescriptorTableEntries GDTEntriesTemplate = { - .Null = { - .Limit0 = 0x0, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = {.Raw = 0x0}, - // .Limit1 = 0x0, - .Flags = {.Raw = 0x0}, - .BaseHigh = 0x0, - }, - + .Null = 0, .Code = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 1, - .S = 1, - .DPL = 0, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ - - .AVL = 0, - .L = 1, - .DB = 0, - .G = 1, - }, - .BaseHigh = 0x0, + .SegmentLimitLow = 0xFFFF, + .BaseAddressLow = 0x0, + .BaseAddressHigh = 0x0, + .Accessed = 0, + .Readable = 1, + .Conforming = 0, + .Executable = 1, + .Type = 1, + .DescriptorPrivilegeLevel = 0, + .Present = 1, + .SegmentLimitHigh = 0xF, + .Available = 0, + .Long = 1, + .Default = 0, + .Granularity = 1, + .BaseAddressHigher = 0x0, }, .Data = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 0, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ - - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, + .SegmentLimitLow = 0xFFFF, + .BaseAddressLow = 0x0, + .BaseAddressHigh = 0x0, + .Accessed = 0, + .Writable = 1, + .ExpandDown = 0, + .Executable = 0, + .Type = 1, + .DescriptorPrivilegeLevel = 0, + .Present = 1, + .SegmentLimitHigh = 0xF, + .Available = 0, + .Reserved = 0, + .Default = 0, + .Granularity = 1, + .BaseAddressHigher = 0x0, }, .UserData = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 0, - .S = 1, - .DPL = 3, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ - - .AVL = 0, - .L = 0, - .DB = 1, - .G = 1, - }, - .BaseHigh = 0x0, + .SegmentLimitLow = 0xFFFF, + .BaseAddressLow = 0x0, + .BaseAddressHigh = 0x0, + .Accessed = 0, + .Writable = 1, + .ExpandDown = 1, + .Executable = 0, + .Type = 1, + .DescriptorPrivilegeLevel = 3, + .Present = 1, + .SegmentLimitHigh = 0xF, + .Available = 0, + .Reserved = 0, + .Default = 0, + .Granularity = 1, + .BaseAddressHigher = 0x0, }, .UserCode = { - .Limit0 = 0xFFFF, - .BaseLow = 0x0, - .BaseMiddle = 0x0, - .Access = { - .A = 0, - .RW = 1, - .DC = 0, - .E = 1, - .S = 1, - .DPL = 3, - .P = 1, - }, - // .Limit1 = 0xF, - .Flags = { - .Reserved = 0xF, /* Workaround for Limit1 */ - - .AVL = 0, - .L = 1, - .DB = 0, - .G = 1, - }, - .BaseHigh = 0x0, + .SegmentLimitLow = 0xFFFF, + .BaseAddressLow = 0x0, + .BaseAddressHigh = 0x0, + .Accessed = 0, + .Readable = 1, + .Conforming = 0, + .Executable = 1, + .Type = 1, + .DescriptorPrivilegeLevel = 3, + .Present = 1, + .SegmentLimitHigh = 0xF, + .Available = 0, + .Long = 1, + .Default = 0, + .Granularity = 1, + .BaseAddressHigher = 0x0, }, - .TaskStateSegment = {}, + .TaskStateSegment{}, }; GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); @@ -156,48 +123,18 @@ namespace GlobalDescriptorTable SafeFunction void Init(int Core) { memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); - gdt[Core] = {.Length = sizeof(GlobalDescriptorTableEntries) - 1, .Entries = &GDTEntries[Core]}; + gdt[Core] = + { + .Limit = sizeof(GlobalDescriptorTableEntries) - 1, + .BaseAddress = &GDTEntries[Core], + }; debug("GDT: %#lx", &gdt[Core]); - debug("GDT KERNEL: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_KERNEL_CODE, - GDTEntries[Core].Code.Limit0, - GDTEntries[Core].Code.BaseLow, - GDTEntries[Core].Code.BaseMiddle, - GDTEntries[Core].Code.Access.Raw, - GDTEntries[Core].Code.Flags.Reserved, - GDTEntries[Core].Code.Flags.Raw & ~0xF, - GDTEntries[Core].Code.BaseHigh); - - debug("GDT KERNEL: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_KERNEL_DATA, - GDTEntries[Core].Data.Limit0, - GDTEntries[Core].Data.BaseLow, - GDTEntries[Core].Data.BaseMiddle, - GDTEntries[Core].Data.Access.Raw, - GDTEntries[Core].Data.Flags.Reserved, - GDTEntries[Core].Data.Flags.Raw & ~0xF, - GDTEntries[Core].Data.BaseHigh); - - debug("GDT USER: CODE %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_USER_CODE, - GDTEntries[Core].UserCode.Limit0, - GDTEntries[Core].UserCode.BaseLow, - GDTEntries[Core].UserCode.BaseMiddle, - GDTEntries[Core].UserCode.Access.Raw, - GDTEntries[Core].UserCode.Flags.Reserved, - GDTEntries[Core].UserCode.Flags.Raw & ~0xF, - GDTEntries[Core].UserCode.BaseHigh); - - debug("GDT USER: DATA %#lx: Limit0: 0x%X, BaseLow: 0x%X, BaseMiddle: 0x%X, Access: 0x%X, Limit1: 0x%X, Flags: 0x%X, BaseHigh: 0x%X", - GDT_USER_DATA, - GDTEntries[Core].UserData.Limit0, - GDTEntries[Core].UserData.BaseLow, - GDTEntries[Core].UserData.BaseMiddle, - GDTEntries[Core].UserData.Access.Raw, - GDTEntries[Core].UserData.Flags.Reserved, - GDTEntries[Core].UserData.Flags.Raw & ~0xF, - GDTEntries[Core].UserData.BaseHigh); + debug("GDT KERNEL CODE %#lx", GDT_KERNEL_CODE); + debug("GDT KERNEL DATA %#lx", GDT_KERNEL_DATA); + debug("GDT USER CODE %#lx", GDT_USER_CODE); + debug("GDT USER DATA %#lx", GDT_USER_DATA); + debug("GDT TSS %#lx", GDT_TSS); CPU::x64::lgdt(&gdt[Core]); @@ -222,13 +159,22 @@ namespace GlobalDescriptorTable uintptr_t Base = (uintptr_t)&tss[Core]; size_t Limit = Base + sizeof(TaskStateSegment); - gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; - gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; - gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; - gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; - gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); - gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; - gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); + SystemSegmentDescriptor *tssDesc = &gdt[Core].BaseAddress->TaskStateSegment; + tssDesc->SegmentLimitLow = Limit & 0xFFFF; + tssDesc->BaseAddressLow = Base & 0xFFFF; + tssDesc->BaseAddressMiddle = (Base >> 16) & 0xFF; + tssDesc->Type = AVAILABLE_64BIT_TSS; + tssDesc->Zero0 = 0; + tssDesc->DescriptorPrivilegeLevel = 0; + tssDesc->Present = 1; + tssDesc->Available = 0; + tssDesc->Reserved0 = 0; + tssDesc->Granularity = 0; + tssDesc->BaseAddressHigh = (Base >> 24) & 0xFF; + tssDesc->BaseAddressHigher = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); + tssDesc->Reserved1 = 0; + tssDesc->Zero1 = 0; + tssDesc->Reserved2 = 0; tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment); tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; diff --git a/Architecture/amd64/cpu/gdt.hpp b/Architecture/amd64/cpu/gdt.hpp index 771075f..e724613 100644 --- a/Architecture/amd64/cpu/gdt.hpp +++ b/Architecture/amd64/cpu/gdt.hpp @@ -19,100 +19,10 @@ #define __FENNIX_KERNEL_GDT_H__ #include +#include namespace GlobalDescriptorTable { - struct TaskStateSegmentEntry - { - /* LOW */ - uint16_t Limit; - uint16_t BaseLow; - uint8_t BaseMiddle; - union GlobalDescriptorTableAccess - { - struct - { - /** - * Access bit. - * - * @note The CPU sets this bit to 1 when the segment - * is accessed. - */ - uint8_t A : 1; - - /** - * Readable bit for code segments, writable bit for data - * segments. - * - * Code Segment: - * This bit must be 1 for the segment to be readable. - * - * Data Segment: - * This bit must be 1 for the segment to be writable. - */ - uint8_t RW : 1; - - /** - * Direction bit for data segments, conforming bit for - * code segments. - * - * Code Segment: - * This bit must be 1 for code in the segment to be - * able to be executed from an equal or lower privilege - * level. - * - * Data Segment: - * This bit must be 1 for the segment to grow up (higher - * addresses). - */ - uint8_t DC : 1; - - /** - * Executable bit. - * - * This bit must be 1 for code-segment descriptors. - * - * This bit must be 0 for data-segment and system - * descriptors. - */ - uint8_t E : 1; - - /** - * Descriptor type. - * - * This bit must be 0 for system descriptors. - * - * This bit must be 1 for code or data segment - * descriptor. - */ - uint8_t S : 1; - - /** - * Descriptor privilege level. - * - * This field determines the privilege level of the - * segment. - * - * 0 = kernel mode - * 3 = user mode - */ - uint8_t DPL : 2; - - /** - * Present bit. - * - * This bit must be 1 for all valid descriptors. - */ - uint8_t P : 1; - } __packed; - uint8_t Raw : 8; - } Access; - uint8_t Granularity; - uint8_t BaseHigh; - /* HIGH */ - uint32_t BaseUpper; - uint32_t Reserved; - } __packed; struct TaskStateSegment { @@ -125,189 +35,20 @@ namespace GlobalDescriptorTable uint16_t IOMapBaseAddressOffset; } __packed; - struct GlobalDescriptorTableEntry - { - /** - * Limit 0:15 - */ - uint16_t Limit0 : 16; - - /** - * Low Base 0:15 - */ - uint16_t BaseLow : 16; - - /** - * Middle Base 16:23 - */ - uint8_t BaseMiddle : 8; - - /** - * Access - */ - union GlobalDescriptorTableAccess - { - struct - { - /** - * Access bit. - * - * @note The CPU sets this bit to 1 when the segment - * is accessed. - */ - uint8_t A : 1; - - /** - * Readable bit for code segments, writable bit for - * data segments. - * - * Code Segment: - * This bit must be 1 for the segment to be readable. - * - * Data Segment: - * This bit must be 1 for the segment to be writable. - */ - uint8_t RW : 1; - - /** - * Direction bit for data segments, conforming bit for - * code segments. - * - * Code Segment: - * This bit must be 1 for code in the segment to be able - * to be executed from an equal or lower privilege level. - * - * Data Segment: - * This bit must be 1 for the segment to grow up (higher - * addresses). - */ - uint8_t DC : 1; - - /** - * Executable bit. - * - * This bit must be 1 for code-segment descriptors. - * - * This bit must be 0 for data-segment and - * system descriptors. - */ - uint8_t E : 1; - - /** - * Descriptor type. - * - * This bit must be 0 for system descriptors. - * - * This bit must be 1 for code or data segment - * descriptor. - */ - uint8_t S : 1; - - /** - * Descriptor privilege level. - * - * This field determines the privilege level of the - * segment. - * - * 0 = kernel mode - * 3 = user mode - */ - uint8_t DPL : 2; - - /** - * Present bit. - * - * This bit must be 1 for all valid descriptors. - */ - uint8_t P : 1; - } __packed; - uint8_t Raw : 8; - } Access; - - // /** Limit 16:19 */ - - // uint16_t Limit1 : 4; - - /** - * Flags - */ - union GlobalDescriptorTableFlags - { - struct - { - /* FIXME: Without this, the kernel crashes. */ - uint8_t Reserved : 4; - - /** - * Available bit. - * - * This bit is available for use by system software. - */ - uint8_t AVL : 1; - - /** - * Long mode. - * - * If the long mode bit is clear, the segment is in - * 32-bit protected mode. - * - * If the long mode bit is set, the segment is in - * 64-bit long mode. - */ - uint8_t L : 1; - - /** - * Size flag. - * - * If the size bit is clear, the segment is in - * 16-bit protected mode. - * - * If the size bit is set, the segment is in - * 32-bit protected mode. - */ - uint8_t DB : 1; - - /** - * Granularity bit. - * - * If the granularity bit is clear, the segment limit - * is in 1 B blocks. - * - * If the granularity bit is set, the segment limit is - * in 4 KiB blocks. - */ - uint8_t G : 1; - } __packed; - uint8_t Raw : 8; - } Flags; - - /** - * High Base 24:31 - */ - uint8_t BaseHigh : 8; - } __packed; - struct GlobalDescriptorTableEntries { - GlobalDescriptorTableEntry Null; - GlobalDescriptorTableEntry Code; - GlobalDescriptorTableEntry Data; - GlobalDescriptorTableEntry UserData; - GlobalDescriptorTableEntry UserCode; - TaskStateSegmentEntry TaskStateSegment; + uint64_t Null; + CodeSegmentDescriptor Code; + DataSegmentDescriptor Data; + DataSegmentDescriptor UserData; + CodeSegmentDescriptor UserCode; + SystemSegmentDescriptor TaskStateSegment; } __packed; struct GlobalDescriptorTableDescriptor { - /** - * GDT entries length - */ - uint16_t Length; - - /** - * GDT entries address - */ - GlobalDescriptorTableEntries *Entries; + uint16_t Limit; + GlobalDescriptorTableEntries *BaseAddress; } __packed; extern void *CPUStackPointer[]; diff --git a/Architecture/amd64/cpu/idt.hpp b/Architecture/amd64/cpu/idt.hpp index 60493a7..a1ad5dd 100644 --- a/Architecture/amd64/cpu/idt.hpp +++ b/Architecture/amd64/cpu/idt.hpp @@ -19,109 +19,10 @@ #define __FENNIX_KERNEL_IDT_H__ #include +#include namespace InterruptDescriptorTable { - /** - * Manual: AMD Architecture Programmer's Manual Volume 2: System Programming - * Subsection: 4.8.3 System Descriptors - * Table: 4-6 - * - * @note Reserved values are not listed in the table. - */ - enum GateType - { - LDT_64BIT = 0b0010, - AVAILABLE_64BIT_TSS = 0b1001, - BUSY_64BIT_TSS = 0b1011, - CALL_GATE_64BIT = 0b1100, - INTERRUPT_GATE_64BIT = 0b1110, - TRAP_GATE_64BIT = 0b1111, - }; - - enum PrivilegeLevelType - { - RING0 = 0b0, - RING1 = 0b1, - RING2 = 0b10, - RING3 = 0b11, - }; - - enum InterruptStackTableType - { - IST0 = 0b0, - IST1 = 0b1, - IST2 = 0b10, - IST3 = 0b11, - IST4 = 0b100, - IST5 = 0b101, - IST6 = 0b110, - }; - - struct InterruptGate - { - /* +0 */ - uint64_t TargetOffsetLow : 16; - uint64_t TargetSelector : 16; - /* +4 */ - uint64_t InterruptStackTable : 3; - uint64_t Reserved0 : 5; - uint64_t Type : 4; - uint64_t Zero : 1; - uint64_t DescriptorPrivilegeLevel : 2; - uint64_t Present : 1; - uint64_t TargetOffsetMiddle : 16; - /* +8 */ - uint64_t TargetOffsetHigh : 32; - /* +12 */ - uint64_t Reserved1 : 32; - } __packed; - - typedef InterruptGate TrapGate; - - struct CallGate - { - /* +0 */ - uint64_t TargetOffsetLow : 16; - uint64_t TargetSelector : 16; - /* +4 */ - uint64_t Reserved0 : 8; - uint64_t Type : 4; - uint64_t Zero0 : 1; - uint64_t DescriptorPrivilegeLevel : 2; - uint64_t Present : 1; - uint64_t TargetOffsetMiddle : 16; - /* +8 */ - uint64_t TargetOffsetHigh : 32; - /* +12 */ - uint64_t Reserved1 : 8; - uint64_t Zero1 : 5; - uint64_t Reserved2 : 19; - } __packed; - - struct SystemSegmentDescriptor - { - /* +0 */ - uint64_t SegmentLimitLow : 16; - uint64_t BaseAddressLow : 16; - /* +4 */ - uint64_t BaseAddressMiddle : 8; - uint64_t Type : 4; - uint64_t Zero0 : 1; - uint64_t DescriptorPrivilegeLevel : 2; - uint64_t Present : 1; - uint64_t SegmentLimitMiddle : 4; - uint64_t Available : 1; - uint64_t Reserved0 : 2; - uint64_t Granularity : 1; - uint64_t BaseAddressHigh : 8; - /* +8 */ - uint64_t BaseAddressHigher : 32; - /* +12 */ - uint64_t Reserved1 : 8; - uint64_t Zero1 : 5; - uint64_t Reserved2 : 19; - } __packed; union IDTGateDescriptor { diff --git a/include/cpu/x86/x64/SegmentDescriptors.hpp b/include/cpu/x86/x64/SegmentDescriptors.hpp new file mode 100644 index 0000000..eeb56b4 --- /dev/null +++ b/include/cpu/x86/x64/SegmentDescriptors.hpp @@ -0,0 +1,168 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#ifndef __FENNIX_KERNEL_SEGMENT_DESCRIPTORS_H__ +#define __FENNIX_KERNEL_SEGMENT_DESCRIPTORS_H__ + +#include + +/** + * Manual: AMD Architecture Programmer's Manual Volume 2: System Programming + * Subsection: 4.8.3 System Descriptors + * Table: 4-6 + * + * @note Reserved values are not listed in the table. + */ +enum GateType +{ + LDT_64BIT = 0b0010, + AVAILABLE_64BIT_TSS = 0b1001, + BUSY_64BIT_TSS = 0b1011, + CALL_GATE_64BIT = 0b1100, + INTERRUPT_GATE_64BIT = 0b1110, + TRAP_GATE_64BIT = 0b1111, +}; + +enum PrivilegeLevelType +{ + RING0 = 0b0, + RING1 = 0b1, + RING2 = 0b10, + RING3 = 0b11, +}; + +enum InterruptStackTableType +{ + IST0 = 0b0, + IST1 = 0b1, + IST2 = 0b10, + IST3 = 0b11, + IST4 = 0b100, + IST5 = 0b101, + IST6 = 0b110, +}; + +struct InterruptGate +{ + /* +0 */ + uint64_t TargetOffsetLow : 16; + uint64_t TargetSelector : 16; + /* +4 */ + uint64_t InterruptStackTable : 3; + uint64_t Reserved0 : 5; + uint64_t Type : 4; + uint64_t Zero : 1; + uint64_t DescriptorPrivilegeLevel : 2; + uint64_t Present : 1; + uint64_t TargetOffsetMiddle : 16; + /* +8 */ + uint64_t TargetOffsetHigh : 32; + /* +12 */ + uint64_t Reserved1 : 32; +} __packed; + +typedef InterruptGate TrapGate; + +struct CallGate +{ + /* +0 */ + uint64_t TargetOffsetLow : 16; + uint64_t TargetSelector : 16; + /* +4 */ + uint64_t Reserved0 : 8; + uint64_t Type : 4; + uint64_t Zero0 : 1; + uint64_t DescriptorPrivilegeLevel : 2; + uint64_t Present : 1; + uint64_t TargetOffsetMiddle : 16; + /* +8 */ + uint64_t TargetOffsetHigh : 32; + /* +12 */ + uint64_t Reserved1 : 8; + uint64_t Zero1 : 5; + uint64_t Reserved2 : 19; +} __packed; + +struct SystemSegmentDescriptor +{ + /* +0 */ + uint64_t SegmentLimitLow : 16; + uint64_t BaseAddressLow : 16; + /* +4 */ + uint64_t BaseAddressMiddle : 8; + uint64_t Type : 4; + uint64_t Zero0 : 1; + uint64_t DescriptorPrivilegeLevel : 2; + uint64_t Present : 1; + uint64_t SegmentLimitMiddle : 4; + uint64_t Available : 1; + uint64_t Reserved0 : 2; + uint64_t Granularity : 1; + uint64_t BaseAddressHigh : 8; + /* +8 */ + uint64_t BaseAddressHigher : 32; + /* +12 */ + uint64_t Reserved1 : 8; + uint64_t Zero1 : 5; + uint64_t Reserved2 : 19; +} __packed; + +struct CodeSegmentDescriptor +{ + /* +0 */ + uint64_t SegmentLimitLow : 16; + uint64_t BaseAddressLow : 16; + /* +4 */ + uint64_t BaseAddressHigh : 8; + uint64_t Accessed : 1; + uint64_t Readable : 1; + uint64_t Conforming : 1; + uint64_t Executable : 1; + uint64_t Type : 1; + uint64_t DescriptorPrivilegeLevel : 2; + uint64_t Present : 1; + uint64_t SegmentLimitHigh : 4; + uint64_t Available : 1; + uint64_t Long : 1; + uint64_t Default : 1; + uint64_t Granularity : 1; + uint64_t BaseAddressHigher : 8; +} __packed; + +struct DataSegmentDescriptor +{ + /* +0 */ + uint64_t SegmentLimitLow : 16; + uint64_t BaseAddressLow : 16; + /* +4 */ + uint64_t BaseAddressHigh : 8; + uint64_t Accessed : 1; + uint64_t Writable : 1; + uint64_t ExpandDown : 1; + uint64_t Executable : 1; + uint64_t Type : 1; + uint64_t DescriptorPrivilegeLevel : 2; + uint64_t Present : 1; + uint64_t SegmentLimitHigh : 4; + uint64_t Available : 1; + uint64_t Reserved : 1; + uint64_t Default : 1; + uint64_t Granularity : 1; + uint64_t BaseAddressHigher : 8; +} __packed; + +#endif // !__FENNIX_KERNEL_SEGMENT_DESCRIPTORS_H__