PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches

Global Descriptor Table. More...

Collaboration diagram for GDT:

Detailed Description

Global Descriptor Table.

The global descriptor table is a legacy feature from the days of 32-bit x86 and older. Most of its features are unused, but is still required in 64-bit mode to specify the current privilage level and to load the TSS.

See also
OSDev Wiki GDT

Data Structures

struct  gdt_desc_t
 GDT descriptor structure. More...
 
struct  gdt_segment_t
 A single GDT segment descriptor. More...
 
struct  gdt_long_system_segment_t
 A long mode system segment descriptor, used for TSS and LDT. More...
 
struct  gdt_t
 The actual GDT structure. More...
 

Macros

#define GDT_RING0   0
 Kernel ring.
 
#define GDT_RING1   1
 Unused ring.
 
#define GDT_RING2   2
 Unused ring.
 
#define GDT_RING3   3
 User ring.
 
#define GDT_NULL   0
 Null segment selector, unused but the gdt must start with it.
 
#define GDT_KERNEL_CODE   0x08
 Kernel code segment selector.
 
#define GDT_KERNEL_DATA   0x10
 Kernel data segment selector.
 
#define GDT_USER_DATA   0x18
 User data segment selector.
 
#define GDT_USER_CODE   0x20
 User code segment selector.
 
#define GDT_TSS   0x28
 TSS segment selector.
 
#define GDT_CS_RING0   (GDT_KERNEL_CODE | GDT_RING0)
 Value to load into the CS register for kernel code.
 
#define GDT_SS_RING0   (GDT_KERNEL_DATA | GDT_RING0)
 Value to load into the SS register for kernel data.
 
#define GDT_CS_RING3   (GDT_USER_CODE | GDT_RING3)
 Value to load into the CS register for user code.
 
#define GDT_SS_RING3   (GDT_USER_DATA | GDT_RING3)
 Value to load into the SS register for user data.
 
#define GDT_ACCESS_ACCESSED   (1 << 0)
 Will be set to 1 when accessed, but its best to set it to 1 manually.
 
#define GDT_ACCESS_READ_WRITE    (1 << 1)
 If set on a code segment, its readable. If set on a data segment, its writable./*#end#*‍/.
 
#define GDT_ACCESS_DIRECTION_CONFORMING    (1 << 2)
 If set on a data segment, the segment grows downwards. If set on a code segment, conforming./*#end#*‍/.
 
#define GDT_ACCESS_EXEC   (1 << 3)
 If set, the segment is a code segment. If clear, its a data segment.
 
#define GDT_ACCESS_SYSTEM   (0 << 4)
 Is a system segment.
 
#define GDT_ACCESS_DATA_CODE   (1 << 4)
 Is a data or code segment.
 
#define GDT_ACCESS_TYPE_LDT   0x2
 Local Descriptor Table. Only used if the SYSTEM bit is 0.
 
#define GDT_ACCESS_TYPE_TSS_AVAILABLE   0x9
 Available 64-bit Task State Segment. Only used if the SYSTEM bit is 0.
 
#define GDT_ACCESS_TYPE_TSS_BUSY   0xB
 Busy 64-bit Task State Segment. Only used if the SYSTEM bit is 0.
 
#define GDT_ACCESS_RING0   (0 << 5)
 Descriptor Privilege Level 0 (kernel).
 
#define GDT_ACCESS_RING1   (1 << 5)
 Descriptor Privilege Level 1, unused.
 
#define GDT_ACCESS_RING2   (2 << 5)
 Descriptor Privilege Level 2, unused.
 
#define GDT_ACCESS_RING3   (3 << 5)
 Descriptor Privilege Level 3 (user).
 
#define GDT_ACCESS_PRESENT   (1 << 7)
 Must be 1 for all valid segments.
 
#define GDT_FLAGS_NONE   0
 No flags set.
 
#define GDT_FLAGS_RESERVED   (1 << 0)
 Must be 0.
 
#define GDT_FLAGS_LONG_MODE   (1 << 1)
 If set, its a 64-bit code segment.
 
#define GDT_FLAGS_SIZE    (1 << 2)
 If set, its a 32-bit segment. If clear, its a 16-bit segment. Ignored in 64-bit mode./*#end#*‍/.
 
#define GDT_FLAGS_4KB   (1 << 3)
 If set, the limit is in 4KiB blocks. If clear, the limit is in bytes.
 

Functions

void gdt_load_descriptor (gdt_desc_t *descriptor)
 Loads a GDT descriptor.
 
void gdt_init (void)
 Initialize the GDT.
 
void gdt_cpu_load (void)
 Load the GDT on the current CPU.
 
void gdt_cpu_tss_load (tss_t *tss)
 Load a TSS into the GDT and load it using the ltr instruction on the current CPU.
 

Macro Definition Documentation

◆ GDT_RING0

#define GDT_RING0   0

Kernel ring.

Definition at line 23 of file gdt.h.

◆ GDT_RING1

#define GDT_RING1   1

Unused ring.

Definition at line 24 of file gdt.h.

◆ GDT_RING2

#define GDT_RING2   2

Unused ring.

Definition at line 25 of file gdt.h.

◆ GDT_RING3

#define GDT_RING3   3

User ring.

Definition at line 26 of file gdt.h.

◆ GDT_NULL

#define GDT_NULL   0

Null segment selector, unused but the gdt must start with it.

Definition at line 28 of file gdt.h.

◆ GDT_KERNEL_CODE

#define GDT_KERNEL_CODE   0x08

Kernel code segment selector.

Definition at line 29 of file gdt.h.

◆ GDT_KERNEL_DATA

#define GDT_KERNEL_DATA   0x10

Kernel data segment selector.

Definition at line 30 of file gdt.h.

◆ GDT_USER_DATA

#define GDT_USER_DATA   0x18

User data segment selector.

Definition at line 31 of file gdt.h.

◆ GDT_USER_CODE

#define GDT_USER_CODE   0x20

User code segment selector.

Definition at line 32 of file gdt.h.

◆ GDT_TSS

#define GDT_TSS   0x28

TSS segment selector.

Definition at line 33 of file gdt.h.

◆ GDT_CS_RING0

#define GDT_CS_RING0   (GDT_KERNEL_CODE | GDT_RING0)

Value to load into the CS register for kernel code.

Definition at line 35 of file gdt.h.

◆ GDT_SS_RING0

#define GDT_SS_RING0   (GDT_KERNEL_DATA | GDT_RING0)

Value to load into the SS register for kernel data.

Definition at line 36 of file gdt.h.

◆ GDT_CS_RING3

#define GDT_CS_RING3   (GDT_USER_CODE | GDT_RING3)

Value to load into the CS register for user code.

Definition at line 38 of file gdt.h.

◆ GDT_SS_RING3

#define GDT_SS_RING3   (GDT_USER_DATA | GDT_RING3)

Value to load into the SS register for user data.

Definition at line 39 of file gdt.h.

◆ GDT_ACCESS_ACCESSED

#define GDT_ACCESS_ACCESSED   (1 << 0)

Will be set to 1 when accessed, but its best to set it to 1 manually.

Definition at line 41 of file gdt.h.

◆ GDT_ACCESS_READ_WRITE

#define GDT_ACCESS_READ_WRITE    (1 << 1)

If set on a code segment, its readable. If set on a data segment, its writable./*#end#*‍/.

Definition at line 43 of file gdt.h.

◆ GDT_ACCESS_DIRECTION_CONFORMING

#define GDT_ACCESS_DIRECTION_CONFORMING    (1 << 2)

If set on a data segment, the segment grows downwards. If set on a code segment, conforming./*#end#*‍/.

Definition at line 45 of file gdt.h.

◆ GDT_ACCESS_EXEC

#define GDT_ACCESS_EXEC   (1 << 3)

If set, the segment is a code segment. If clear, its a data segment.

Definition at line 46 of file gdt.h.

◆ GDT_ACCESS_SYSTEM

#define GDT_ACCESS_SYSTEM   (0 << 4)

Is a system segment.

Definition at line 47 of file gdt.h.

◆ GDT_ACCESS_DATA_CODE

#define GDT_ACCESS_DATA_CODE   (1 << 4)

Is a data or code segment.

Definition at line 48 of file gdt.h.

◆ GDT_ACCESS_TYPE_LDT

#define GDT_ACCESS_TYPE_LDT   0x2

Local Descriptor Table. Only used if the SYSTEM bit is 0.

Definition at line 50 of file gdt.h.

◆ GDT_ACCESS_TYPE_TSS_AVAILABLE

#define GDT_ACCESS_TYPE_TSS_AVAILABLE   0x9

Available 64-bit Task State Segment. Only used if the SYSTEM bit is 0.

Definition at line 51 of file gdt.h.

◆ GDT_ACCESS_TYPE_TSS_BUSY

#define GDT_ACCESS_TYPE_TSS_BUSY   0xB

Busy 64-bit Task State Segment. Only used if the SYSTEM bit is 0.

Definition at line 52 of file gdt.h.

◆ GDT_ACCESS_RING0

#define GDT_ACCESS_RING0   (0 << 5)

Descriptor Privilege Level 0 (kernel).

Definition at line 54 of file gdt.h.

◆ GDT_ACCESS_RING1

#define GDT_ACCESS_RING1   (1 << 5)

Descriptor Privilege Level 1, unused.

Definition at line 55 of file gdt.h.

◆ GDT_ACCESS_RING2

#define GDT_ACCESS_RING2   (2 << 5)

Descriptor Privilege Level 2, unused.

Definition at line 56 of file gdt.h.

◆ GDT_ACCESS_RING3

#define GDT_ACCESS_RING3   (3 << 5)

Descriptor Privilege Level 3 (user).

Definition at line 57 of file gdt.h.

◆ GDT_ACCESS_PRESENT

#define GDT_ACCESS_PRESENT   (1 << 7)

Must be 1 for all valid segments.

Definition at line 59 of file gdt.h.

◆ GDT_FLAGS_NONE

#define GDT_FLAGS_NONE   0

No flags set.

Definition at line 61 of file gdt.h.

◆ GDT_FLAGS_RESERVED

#define GDT_FLAGS_RESERVED   (1 << 0)

Must be 0.

Definition at line 62 of file gdt.h.

◆ GDT_FLAGS_LONG_MODE

#define GDT_FLAGS_LONG_MODE   (1 << 1)

If set, its a 64-bit code segment.

Definition at line 63 of file gdt.h.

◆ GDT_FLAGS_SIZE

#define GDT_FLAGS_SIZE    (1 << 2)

If set, its a 32-bit segment. If clear, its a 16-bit segment. Ignored in 64-bit mode./*#end#*‍/.

Definition at line 65 of file gdt.h.

◆ GDT_FLAGS_4KB

#define GDT_FLAGS_4KB   (1 << 3)

If set, the limit is in 4KiB blocks. If clear, the limit is in bytes.

Definition at line 66 of file gdt.h.

Function Documentation

◆ gdt_load_descriptor()

void gdt_load_descriptor ( gdt_desc_t descriptor)
extern

Loads a GDT descriptor.

Dont use this directly use gdt_cpu_load() instead.

Parameters
descriptorThe GDT descriptor to load.
Here is the caller graph for this function:

◆ gdt_init()

void gdt_init ( void  )

Initialize the GDT.

This will setup the GDT structure in memory, but will not load it. Loading is done in gdt_cpu_load().

Definition at line 36 of file gdt.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ gdt_cpu_load()

void gdt_cpu_load ( void  )

Load the GDT on the current CPU.

This will load the GDT using the lgdt instruction and then reload all segment registers to use the new GDT.

Must be called after gdt_init().

Definition at line 56 of file gdt.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ gdt_cpu_tss_load()

void gdt_cpu_tss_load ( tss_t tss)

Load a TSS into the GDT and load it using the ltr instruction on the current CPU.

Note that the actual TTS descriptor in the GDT can be shared between CPUs, as its only used while loading the TSS, after that its just useless.

Parameters
tssThe TSS to load.

Definition at line 64 of file gdt.c.

Here is the call graph for this function:
Here is the caller graph for this function: