Global Descriptor Table (GDT) & Task State Segment (TSS)
The GDT is a fundamental x86 structure that defines memory segments and their access rights. TilekarOS uses a Flat Memory Model, where segments cover the entire 4GB address space.
1. Segment Descriptors
TilekarOS defines five main descriptors in the GDT:
| Index | Offset | Description | Base | Limit | Privilege |
|---|---|---|---|---|---|
| 0 | 0x00 | Null | - | - | - |
| 1 | 0x08 | Kernel Code | 0 | 4GB | Ring 0 |
| 2 | 0x10 | Kernel Data | 0 | 4GB | Ring 0 |
| 3 | 0x18 | User Code | 0 | 4GB | Ring 3 |
| 4 | 0x20 | User Data | 0 | 4GB | Ring 3 |
| 5 | 0x28 | TSS | &tss | size | Ring 3 |
Segment Format
Each GDT entry is 8 bytes and includes the Base Address (32-bit), Segment Limit (20-bit), and control bits:
- Access Byte:
- P (Present): Must be 1.
- DPL (Privilege): 00 for Kernel, 11 for User.
- Type: Code (0x18) or Data (0x10).
- Flags:
- G (Granularity): 1 for 4KB blocks (allows 4GB limit).
- D (Size): 1 for 32-bit protected mode.
2. Task State Segment (TSS)
While TilekarOS uses software-based multitasking, it still requires one hardware TSS to handle privilege transitions (e.g., from User Mode to Kernel Mode).
Why do we need it?
When an interrupt occurs while the CPU is in Ring 3, it needs to switch to a safe Ring 0 stack. The CPU looks up the esp0 field in the TSS to find the kernel stack pointer for the current task.
Implementation
TSSEntryStructure: Contains pointers for all privilege levels (esp0,esp1,esp2) and current registers. TilekarOS primarily uses theesp0andss0fields.tss_entry: A global structure containing theesp0andss0values.tss_set_kernel_stack(uint32_t stack_base): Updatesesp0during every context switch so that the CPU always uses the correct kernel stack for the active task.
3. Loading the GDT
The GDT is loaded into the CPU using the lgdt instruction. After loading, the segment registers (cs, ds, es, fs, gs, ss) must be reloaded to point to the new descriptors.