Introduce boot.mgr - a self-registering, dependency-ordered boot initialization framework with barrier-based phasing and glob pattern matching. Units now declare their own init procedures and dependencies via registerBoot()/registerBarrier() in their initialization sections, boot.mgr.run() topologically sorts and executes them. - Add src/boot/boot.mgr.pas with topoSort, glob matching, barrier two-pass algorithm, and boot tree printer - Gut src/asuro.pas (kmain): now just stores multiboot info, calls System.init(), boot.mgr.run, and yield() - Add initialization sections with registerBoot() to 53 existing units - Add new units: core.pas, test.pas, driver.storage.boot.pas, app.wasm.pas, app.bsod.pas (factored out of asuro.pas) - Define 9 barrier phases: immediate -> early -> middle -> storage -> bus -> device -> bus.late -> late -> final - Fix xHCI ISR: exclude PRC/WRC from PORTSC change bit clearing to prevent race with port reset busy-wait - Fix driver.bus.usb.core fire_completion_hooks: guard against uint32 underflow when CompletionHookCount = 0 - Move auto_mount_volumes from device barrier to late barrier so it runs after PCI scan discovers storage controllers - Add toolchain/compile_initcalls.sh for boot entry extraction - Add Boot Registration sections to all 51 doc files; create 4 new doc files; rewrite boot.mgr.md; update mkdocs.yml nav
3.6 KiB
arch.x86.gdt
Global Descriptor Table (GDT) data structures, gate management, and loading.
Overview
This unit defines the GDT data structures and provides procedures to set individual segment descriptors, flush the GDT into the CPU via LGDT, and reload it after modification. During init, five standard descriptors are installed: a null segment, a ring-0 code segment, a ring-0 data segment, a ring-3 code segment, and a ring-3 data segment. The GDT can hold up to 1024 entries; the GDT pointer limit is updated automatically as new gates are added.
Dependencies
io.syslog
Boot Registration
Registered with boot.mgr as arch.x86.gdt at the early barrier.
Types
TGDT_Entry / PGDT_Entry
TGDT_Entry = packed record
limit_low : uint16;
base_low : uint16;
base_middle : uint8;
access : uint8;
granularity : uint8;
base_high : uint8;
end;
An 8-byte x86 segment descriptor in the standard hardware layout.
| Field | Description |
|---|---|
| limit_low | Lower 16 bits of the segment limit |
| base_low | Lower 16 bits of the segment base address |
| base_middle | Bits 16–23 of the segment base address |
| access | Access byte: present, DPL, type flags |
| granularity | Upper 4 bits of limit plus granularity/size flags |
| base_high | Bits 24–31 of the segment base address |
TGDT_Pointer
TGDT_Pointer = packed record
limit : uint16;
base : uint32;
end;
The 6-byte structure passed to the LGDT instruction. limit is the byte size of the GDT minus one; base is the linear address of the first GDT entry.
Variables
gdt_entries
var gdt_entries : array[0..1023] of TGDT_Entry;
Static array holding up to 1024 GDT descriptors.
gdt_pointer
var gdt_pointer : TGDT_Pointer;
The LGDT operand. base is set to the address of gdt_entries; limit grows as gates are added.
Functions and Procedures
init
procedure init();
Initialises the GDT with five standard entries and calls flush to load it:
| Gate | Offset | Access | Description |
|---|---|---|---|
| 0 | 0x00 | 0x00 | Null descriptor |
| 1 | 0x08 | 0x9A | Ring-0 code (execute/read, 4 GB flat) |
| 2 | 0x10 | 0x92 | Ring-0 data (read/write, 4 GB flat) |
| 3 | 0x18 | 0xFA | Ring-3 code (execute/read, 4 GB flat) |
| 4 | 0x20 | 0xF2 | Ring-3 data (read/write, 4 GB flat) |
set_gate
procedure set_gate(Gate_Number : uint32; Base : uint32; Limit : uint32; Access : uint8; Granularity : uint8);
Writes a single GDT descriptor at index Gate_Number. Splits Base and Limit across the appropriate fields of the TGDT_Entry record. Automatically updates gdt_pointer.limit if the new gate extends beyond the current table boundary.
flush
procedure flush;
Loads the GDT via LGDT and reloads all data segment registers (DS, ES, FS, GS, SS) with selector 0x10 (ring-0 data). A far jump to selector 0x08 (ring-0 code) flushes the instruction pipeline and reloads CS.
reload
procedure reload;
Reissues LGDT without touching segment registers. Used after adding descriptors such as a TSS when the existing segment mappings remain valid.
Notes
- The far jump in
flush_gdtis hand-assembled usingdb/dwdirectives because the Free Pascal inline assembler does not support far-jump syntax directly. - Gates are numbered from 0; the segment selector for gate N is N * 8 with the lower 3 bits encoding the requested privilege level.
- The table supports up to 1024 descriptors (8 KiB), which is the hardware maximum for a 32-bit protected-mode GDT.