Update GDT & IDT structures

This commit is contained in:
Alex 2023-08-25 02:53:35 +03:00
parent 05610c7e7a
commit 622214003f
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
4 changed files with 270 additions and 514 deletions

View File

@ -25,117 +25,84 @@
namespace GlobalDescriptorTable namespace GlobalDescriptorTable
{ {
static GlobalDescriptorTableEntries GDTEntriesTemplate = { static GlobalDescriptorTableEntries GDTEntriesTemplate = {
.Null = { .Null = 0,
.Limit0 = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.Raw = 0x0},
// .Limit1 = 0x0,
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0,
},
.Code = { .Code = {
.Limit0 = 0xFFFF, .SegmentLimitLow = 0xFFFF,
.BaseLow = 0x0, .BaseAddressLow = 0x0,
.BaseMiddle = 0x0, .BaseAddressHigh = 0x0,
.Access = { .Accessed = 0,
.A = 0, .Readable = 1,
.RW = 1, .Conforming = 0,
.DC = 0, .Executable = 1,
.E = 1, .Type = 1,
.S = 1, .DescriptorPrivilegeLevel = 0,
.DPL = 0, .Present = 1,
.P = 1, .SegmentLimitHigh = 0xF,
}, .Available = 0,
// .Limit1 = 0xF, .Long = 1,
.Flags = { .Default = 0,
.Reserved = 0xF, /* Workaround for Limit1 */ .Granularity = 1,
.BaseAddressHigher = 0x0,
.AVL = 0,
.L = 1,
.DB = 0,
.G = 1,
},
.BaseHigh = 0x0,
}, },
.Data = { .Data = {
.Limit0 = 0xFFFF, .SegmentLimitLow = 0xFFFF,
.BaseLow = 0x0, .BaseAddressLow = 0x0,
.BaseMiddle = 0x0, .BaseAddressHigh = 0x0,
.Access = { .Accessed = 0,
.A = 0, .Writable = 1,
.RW = 1, .ExpandDown = 0,
.DC = 0, .Executable = 0,
.E = 0, .Type = 1,
.S = 1, .DescriptorPrivilegeLevel = 0,
.DPL = 0, .Present = 1,
.P = 1, .SegmentLimitHigh = 0xF,
}, .Available = 0,
// .Limit1 = 0xF, .Reserved = 0,
.Flags = { .Default = 0,
.Reserved = 0xF, /* Workaround for Limit1 */ .Granularity = 1,
.BaseAddressHigher = 0x0,
.AVL = 0,
.L = 0,
.DB = 1,
.G = 1,
},
.BaseHigh = 0x0,
}, },
.UserData = { .UserData = {
.Limit0 = 0xFFFF, .SegmentLimitLow = 0xFFFF,
.BaseLow = 0x0, .BaseAddressLow = 0x0,
.BaseMiddle = 0x0, .BaseAddressHigh = 0x0,
.Access = { .Accessed = 0,
.A = 0, .Writable = 1,
.RW = 1, .ExpandDown = 1,
.DC = 0, .Executable = 0,
.E = 0, .Type = 1,
.S = 1, .DescriptorPrivilegeLevel = 3,
.DPL = 3, .Present = 1,
.P = 1, .SegmentLimitHigh = 0xF,
}, .Available = 0,
// .Limit1 = 0xF, .Reserved = 0,
.Flags = { .Default = 0,
.Reserved = 0xF, /* Workaround for Limit1 */ .Granularity = 1,
.BaseAddressHigher = 0x0,
.AVL = 0,
.L = 0,
.DB = 1,
.G = 1,
},
.BaseHigh = 0x0,
}, },
.UserCode = { .UserCode = {
.Limit0 = 0xFFFF, .SegmentLimitLow = 0xFFFF,
.BaseLow = 0x0, .BaseAddressLow = 0x0,
.BaseMiddle = 0x0, .BaseAddressHigh = 0x0,
.Access = { .Accessed = 0,
.A = 0, .Readable = 1,
.RW = 1, .Conforming = 0,
.DC = 0, .Executable = 1,
.E = 1, .Type = 1,
.S = 1, .DescriptorPrivilegeLevel = 3,
.DPL = 3, .Present = 1,
.P = 1, .SegmentLimitHigh = 0xF,
}, .Available = 0,
// .Limit1 = 0xF, .Long = 1,
.Flags = { .Default = 0,
.Reserved = 0xF, /* Workaround for Limit1 */ .Granularity = 1,
.BaseAddressHigher = 0x0,
.AVL = 0,
.L = 1,
.DB = 0,
.G = 1,
},
.BaseHigh = 0x0,
}, },
.TaskStateSegment = {}, .TaskStateSegment{},
}; };
GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16); GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16);
@ -156,48 +123,18 @@ namespace GlobalDescriptorTable
SafeFunction void Init(int Core) SafeFunction void Init(int Core)
{ {
memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries)); 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: %#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", debug("GDT KERNEL CODE %#lx", GDT_KERNEL_CODE);
GDT_KERNEL_CODE, debug("GDT KERNEL DATA %#lx", GDT_KERNEL_DATA);
GDTEntries[Core].Code.Limit0, debug("GDT USER CODE %#lx", GDT_USER_CODE);
GDTEntries[Core].Code.BaseLow, debug("GDT USER DATA %#lx", GDT_USER_DATA);
GDTEntries[Core].Code.BaseMiddle, debug("GDT TSS %#lx", GDT_TSS);
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);
CPU::x64::lgdt(&gdt[Core]); CPU::x64::lgdt(&gdt[Core]);
@ -222,13 +159,22 @@ namespace GlobalDescriptorTable
uintptr_t Base = (uintptr_t)&tss[Core]; uintptr_t Base = (uintptr_t)&tss[Core];
size_t Limit = Base + sizeof(TaskStateSegment); size_t Limit = Base + sizeof(TaskStateSegment);
gdt[Core].Entries->TaskStateSegment.Limit = Limit & 0xFFFF; SystemSegmentDescriptor *tssDesc = &gdt[Core].BaseAddress->TaskStateSegment;
gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; tssDesc->SegmentLimitLow = Limit & 0xFFFF;
gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF; tssDesc->BaseAddressLow = Base & 0xFFFF;
gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF; tssDesc->BaseAddressMiddle = (Base >> 16) & 0xFF;
gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); tssDesc->Type = AVAILABLE_64BIT_TSS;
gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; tssDesc->Zero0 = 0;
gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); 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].IOMapBaseAddressOffset = sizeof(TaskStateSegment);
tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE; tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE;

View File

@ -19,100 +19,10 @@
#define __FENNIX_KERNEL_GDT_H__ #define __FENNIX_KERNEL_GDT_H__
#include <types.h> #include <types.h>
#include <cpu/x86/x64/SegmentDescriptors.hpp>
namespace GlobalDescriptorTable 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 struct TaskStateSegment
{ {
@ -125,189 +35,20 @@ namespace GlobalDescriptorTable
uint16_t IOMapBaseAddressOffset; uint16_t IOMapBaseAddressOffset;
} __packed; } __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 struct GlobalDescriptorTableEntries
{ {
GlobalDescriptorTableEntry Null; uint64_t Null;
GlobalDescriptorTableEntry Code; CodeSegmentDescriptor Code;
GlobalDescriptorTableEntry Data; DataSegmentDescriptor Data;
GlobalDescriptorTableEntry UserData; DataSegmentDescriptor UserData;
GlobalDescriptorTableEntry UserCode; CodeSegmentDescriptor UserCode;
TaskStateSegmentEntry TaskStateSegment; SystemSegmentDescriptor TaskStateSegment;
} __packed; } __packed;
struct GlobalDescriptorTableDescriptor struct GlobalDescriptorTableDescriptor
{ {
/** uint16_t Limit;
* GDT entries length GlobalDescriptorTableEntries *BaseAddress;
*/
uint16_t Length;
/**
* GDT entries address
*/
GlobalDescriptorTableEntries *Entries;
} __packed; } __packed;
extern void *CPUStackPointer[]; extern void *CPUStackPointer[];

View File

@ -19,109 +19,10 @@
#define __FENNIX_KERNEL_IDT_H__ #define __FENNIX_KERNEL_IDT_H__
#include <types.h> #include <types.h>
#include <cpu/x86/x64/SegmentDescriptors.hpp>
namespace InterruptDescriptorTable 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 union IDTGateDescriptor
{ {

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_SEGMENT_DESCRIPTORS_H__
#define __FENNIX_KERNEL_SEGMENT_DESCRIPTORS_H__
#include <types.h>
/**
* 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__