MentOS  0.8.0
The Mentoring Operating System
Classes | Macros | Typedefs | Enumerations | Functions
Global Descriptor Table (GDT)

Is used to define the characteristics of the various memory areas used during program execution, including the base address, the size and access privileges like executability and writability. More...

Classes

struct  gdt_descriptor_t
 Data structure representing a GDT descriptor. More...
 
struct  gdt_pointer_t
 Data structure used to load the GDT into the GDTR. More...
 

Macros

#define IDT_PADDING   14U
 Used in IDT for padding.
 

Typedefs

typedef struct gdt_descriptor_t _syscall0 = _syscall0( (packed) )= _syscall1( (packed) )= _syscall2( (packed) )= _syscall3( (packed) )= gdt_descriptor_t
 Data structure representing a GDT descriptor. More...
 

Enumerations

enum  gdt_bits_t {
  GDT_PRESENT = 128U , GDT_KERNEL = 0U , GDT_USER = 96U , GDT_S = 16U ,
  GDT_EX = 8U , GDT_DC = 4U , GDT_RW = 2U , GDT_AC = 1U ,
  GDT_CODE = (GDT_S | GDT_EX) , GDT_DATA = (GDT_S | GDT_RW) , GDT_GRANULARITY = 128U , GDT_OPERAND_SIZE = 64U
}
 Bitmasks used to access to specific bits of the GDT. More...
 

Functions

void init_gdt (void)
 Initialise the GDT. More...
 
void gdt_set_gate (uint8_t index, uint32_t base, uint32_t limit, uint8_t access, uint8_t granul)
 Sets the value of one GDT entry. More...
 

Detailed Description

Is used to define the characteristics of the various memory areas used during program execution, including the base address, the size and access privileges like executability and writability.

Typedef Documentation

◆ _syscall0

typedef struct page_directory_t _syscall0 = _syscall0( (packed) )= _syscall1( (packed) )= _syscall2( (packed) )= _syscall3( (packed) )= gdt_descriptor_t

Data structure representing a GDT descriptor.

A page directory.

A pointer structure used for informing the CPU about our IDT.

Data structure used to load the GDT into the GDTR.

In the two-level paging, this is the first level.

Enumeration Type Documentation

◆ gdt_bits_t

enum gdt_bits_t

Bitmasks used to access to specific bits of the GDT.

PRIV (Privilege bits)

Contains the ring level, specifically:

  • 00 (0) = highest (kernel),
  • 11 (3) = lowest (user applications).

S (Descriptor type)

This bit should be set for code or data segments and should be cleared for system segments (eg. a Task State Segment).

EX (Executable bit)

  • If 1 code in this segment can be executed, ie. a code selector.
  • If 0 it is a data selector.

DC (Direction bit/Conforming bit)

Direction bit for data selectors: Tells the direction. 0 the segment grows up. 1 the segment grows down, ie., the offset has to be greater than the limit.

Conforming bit for code selectors:

  • If 1 code in this segment can be executed from an equal or lower privilege level. For example, code in ring 3 can far-jump to conforming code in a ring 2 segment. The privl-bits represent the highest privilege level that is allowed to execute the segment. For example, code in ring 0 cannot far-jump to a conforming code segment with privl==0x2, while code in ring 2 and 3 can. Note that the privilege level remains the same, ie. a far-jump form ring 3 to a privl==2-segment remains in ring 3 after the jump.
  • If 0 code in this segment can only be executed from the ring set in privl.

RW (Readable bit/Writable bit)

  • Readable bit for code selectors:
    • Whether read access for this segment is allowed.
    • Write access is never allowed for code segments.
  • Writable bit for data selectors:
    • Whether write access for this segment is allowed.
    • Read access is always allowed for data segments.

AC (Accessed bit)

Just set to 0. The CPU sets this to 1 when the segment is accessed.

GR (Granularity bit)

  • If 0 the limit is in 1 B blocks (byte granularity);
  • if 1 the limit is in 4 KiB blocks (page granularity).

SZ (Size bit)

  • If 0 the selector defines 16 bit protected mode;
  • if 1 it defines 32 bit protected mode.

You can have both 16 bit and 32 bit selectors at once.

Enumerator
GDT_PRESENT 

0b10000000U (Present): This must be 1 for all valid selectors.

GDT_KERNEL 

0b00000000U (Privilege): Sets the 2 privilege bits (ring level) to 0 = highest (kernel).

GDT_USER 

0b01100000U (Privilege): Sets the 2 privilege bits (ring level) to 3 = lowest (user applications).

GDT_S 

0b00010000U (Descriptor): This bit should be set for code or data segments and should be cleared for system segments (eg. a Task State Segment)

GDT_EX 

0b00001000U (Executable): If 1 code in this segment can be executed, ie. a code selector. If 0 it is a data selector.

GDT_DC 

0b00000100U (Direction/Conforming)

GDT_RW 

0b00000010U (Readable/Writable)

GDT_AC 

0b00000001U (Accessed): Just set to 0. The CPU sets this to 1 when the segment is accessed.

GDT_CODE 

0b00001100U (Executable Code): Identifies an executable code segment.

GDT_DATA 

0b00001001U (Writable Data): Identifies a writable data segment.

GDT_GRANULARITY 

0b10000000U (Granularity): If 0 the limit is in 1 B blocks (byte granularity), if 1 the limit is in 4 KiB blocks (page granularity).

GDT_OPERAND_SIZE 

0b01000000U (Size): If 0 the selector defines 16 bit protected mode. If 1 it defines 32 bit protected mode. You can have both 16 bit and 32 bit selectors at once.

Function Documentation

◆ gdt_set_gate()

void gdt_set_gate ( uint8_t  index,
uint32_t  base,
uint32_t  limit,
uint8_t  access,
uint8_t  granul 
)

Sets the value of one GDT entry.

Parameters
indexThe index inside the GDT.
baseMemory address where the segment we are defining starts.
limitThe memory address which determines the end of the segnment.
accessType (4bit) - S (1) bit -DPL (2 bit) - P(1 bit).
granulSegLimit_hi(4 bit) AVL(1 bit) L(1 bit) D/B(1 bit) G(1bit).

◆ init_gdt()

void init_gdt ( void  )

Initialise the GDT.

This will setup the special GDT pointer, set up the first 3 entries in our GDT, and then finally call gdt_flush() in our assembler file in order to tell the processor where the new GDT is and update the new segment registers.